const LocalDatabase = require('../config/LocalDatabase');
const logger = require('../utils/logger');

/**
 * Mod Model - Handles mod data in local database
 */
class ModModel {
  static async create(modData) {
    const {
      name,
      version,
      author,
      description,
      filePath,
      checksum,
      dependencies,
      config
    } = modData;

    const sql = `
      INSERT INTO mods (name, version, author, description, file_path, checksum, dependencies, config)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `;
    
    const result = await LocalDatabase.run(sql, [
      name,
      version,
      author,
      description || null,
      filePath,
      checksum || null,
      dependencies ? JSON.stringify(dependencies) : null,
      config ? JSON.stringify(config) : null
    ]);

    return await this.findById(result.id);
  }

  static async findById(id) {
    const sql = 'SELECT * FROM mods WHERE id = ?';
    const mod = await LocalDatabase.get(sql, [id]);
    return this.parseMod(mod);
  }

  static async findByName(name) {
    const sql = 'SELECT * FROM mods WHERE name = ?';
    const mod = await LocalDatabase.get(sql, [name]);
    return this.parseMod(mod);
  }

  static async findAll(enabledOnly = false) {
    const sql = enabledOnly 
      ? 'SELECT * FROM mods WHERE enabled = 1 ORDER BY name'
      : 'SELECT * FROM mods ORDER BY name';
    
    const mods = await LocalDatabase.all(sql);
    return mods.map(mod => this.parseMod(mod));
  }

  static async update(id, updates) {
    const fields = [];
    const values = [];

    Object.keys(updates).forEach(key => {
      if (key === 'dependencies' || key === 'config') {
        fields.push(`${key} = ?`);
        values.push(JSON.stringify(updates[key]));
      } else {
        fields.push(`${key} = ?`);
        values.push(updates[key]);
      }
    });

    if (fields.length === 0) return false;

    fields.push('updated_at = CURRENT_TIMESTAMP');
    values.push(id);

    const sql = `UPDATE mods SET ${fields.join(', ')} WHERE id = ?`;
    const result = await LocalDatabase.run(sql, values);
    
    return result.changes > 0;
  }

  static async delete(id) {
    const sql = 'DELETE FROM mods WHERE id = ?';
    const result = await LocalDatabase.run(sql, [id]);
    return result.changes > 0;
  }

  static async enable(id) {
    return await this.update(id, { enabled: 1 });
  }

  static async disable(id) {
    return await this.update(id, { enabled: 0 });
  }

  static async getLoadOrder() {
    const sql = `
      SELECT m.*, ml.load_order
      FROM mods m
      LEFT JOIN mod_load_order ml ON m.id = ml.mod_id
      WHERE m.enabled = 1
      ORDER BY ml.load_order ASC, m.name ASC
    `;
    
    const mods = await LocalDatabase.all(sql);
    return mods.map(mod => this.parseMod(mod));
  }

  static async setLoadOrder(modIds) {
    await LocalDatabase.run('DELETE FROM mod_load_order');
    
    for (let i = 0; i < modIds.length; i++) {
      await LocalDatabase.run(
        'INSERT INTO mod_load_order (mod_id, load_order) VALUES (?, ?)',
        [modIds[i], i + 1]
      );
    }
    
    return true;
  }

  static parseMod(mod) {
    if (!mod) return null;
    
    return {
      ...mod,
      enabled: Boolean(mod.enabled),
      dependencies: mod.dependencies ? JSON.parse(mod.dependencies) : null,
      config: mod.config ? JSON.parse(mod.config) : null
    };
  }
}

/**
 * ModAsset Model - Handles mod assets in local database
 */
class ModAssetModel {
  static async create(assetData) {
    const { modId, assetType, assetId, assetData: data } = assetData;

    const sql = `
      INSERT OR REPLACE INTO mod_assets (mod_id, asset_type, asset_id, asset_data)
      VALUES (?, ?, ?, ?)
    `;
    
    const result = await LocalDatabase.run(sql, [
      modId,
      assetType,
      assetId,
      JSON.stringify(data)
    ]);

    return await this.findById(result.id);
  }

  static async findById(id) {
    const sql = 'SELECT * FROM mod_assets WHERE id = ?';
    const asset = await LocalDatabase.get(sql, [id]);
    return this.parseAsset(asset);
  }

  static async findByModId(modId) {
    const sql = 'SELECT * FROM mod_assets WHERE mod_id = ?';
    const assets = await LocalDatabase.all(sql, [modId]);
    return assets.map(asset => this.parseAsset(asset));
  }

  static async findByType(assetType) {
    const sql = `
      SELECT ma.*, m.name as mod_name, m.enabled as mod_enabled
      FROM mod_assets ma
      JOIN mods m ON ma.mod_id = m.id
      WHERE ma.asset_type = ? AND m.enabled = 1
      ORDER BY m.name, ma.asset_id
    `;
    
    const assets = await LocalDatabase.all(sql, [assetType]);
    return assets.map(asset => this.parseAsset(asset));
  }

  static async findByTypeAndId(assetType, assetId) {
    const sql = `
      SELECT ma.*, m.name as mod_name, m.enabled as mod_enabled
      FROM mod_assets ma
      JOIN mods m ON ma.mod_id = m.id
      WHERE ma.asset_type = ? AND ma.asset_id = ? AND m.enabled = 1
    `;
    
    const asset = await LocalDatabase.get(sql, [assetType, assetId]);
    return this.parseAsset(asset);
  }

  static async delete(id) {
    const sql = 'DELETE FROM mod_assets WHERE id = ?';
    const result = await LocalDatabase.run(sql, [id]);
    return result.changes > 0;
  }

  static async deleteByModId(modId) {
    const sql = 'DELETE FROM mod_assets WHERE mod_id = ?';
    const result = await LocalDatabase.run(sql, [modId]);
    return result.changes > 0;
  }

  static parseAsset(asset) {
    if (!asset) return null;
    
    return {
      ...asset,
      assetData: JSON.parse(asset.asset_data),
      modEnabled: Boolean(asset.mod_enabled)
    };
  }
}

/**
 * ServerModPreferences Model - Handles server mod preferences
 */
class ServerModPreferencesModel {
  static async set(key, value) {
    const sql = `
      INSERT OR REPLACE INTO server_mod_preferences (key, value, updated_at)
      VALUES (?, ?, CURRENT_TIMESTAMP)
    `;
    
    const result = await LocalDatabase.run(sql, [key, JSON.stringify(value)]);
    return result.changes > 0;
  }

  static async get(key) {
    const sql = 'SELECT * FROM server_mod_preferences WHERE key = ?';
    const pref = await LocalDatabase.get(sql, [key]);
    
    if (!pref) return null;
    return JSON.parse(pref.value);
  }

  static async getAll() {
    const sql = 'SELECT * FROM server_mod_preferences';
    const prefs = await LocalDatabase.all(sql);
    
    const result = {};
    prefs.forEach(pref => {
      result[pref.key] = JSON.parse(pref.value);
    });
    
    return result;
  }

  static async delete(key) {
    const sql = 'DELETE FROM server_mod_preferences WHERE key = ?';
    const result = await LocalDatabase.run(sql, [key]);
    return result.changes > 0;
  }
}

module.exports = {
  ModModel,
  ModAssetModel,
  ServerModPreferencesModel
};
