#!/usr/bin/env node

const Database = require('better-sqlite3');
const mysql = require('mysql2/promise');
const path = require('path');
const dotenv = require('dotenv');

dotenv.config({ path: path.join(__dirname, '.env') });
dotenv.config({ path: path.join(__dirname, '..', '.env') });

if (!process.env.DB_PASSWORD) {
  throw new Error('DB_PASSWORD must be set in database/.env or .env');
}

// SQLite database path
const sqliteDbPath = path.join(__dirname, 'sqlite', 'deathwatch.db');

// MariaDB configuration
const mariadbConfig = {
  host: process.env.DB_HOST || '192.168.1.113',
  user: process.env.DB_USER || 'deathwatch',
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME || 'deathwatch',
  port: Number(process.env.DB_PORT || 3307)
};

// Helper function to convert SQLite datetime to MySQL format
function convertDateTime(dateString) {
  if (!dateString) return null;
  try {
    return new Date(dateString).toISOString().slice(0, 19).replace('T', ' ');
  } catch (error) {
    console.warn(`Warning: Could not convert datetime: ${dateString}`);
    return null;
  }
}

async function migrateData() {
  let sqliteDb = null;
  let mariadbConnection = null;

  try {
    console.log('Starting data migration from SQLite to MariaDB...');
    
    // Connect to SQLite
    console.log('Connecting to SQLite database...');
    sqliteDb = new Database(sqliteDbPath);
    
    // Connect to MariaDB
    console.log('Connecting to MariaDB database...');
    mariadbConnection = await mysql.createConnection(mariadbConfig);
    
    // Migrate players table (includes requisition_points and renown_level)
    console.log('Migrating players table...');
    const players = sqliteDb.prepare('SELECT * FROM players').all();
    console.log(`Found ${players.length} players to migrate`);
    
    for (const player of players) {
      console.log(`  Migrating player: ${player.name}`);
      
      // Convert text fields to proper JSON
      const rollerInfo = player.roller_info || '{}';
      const shopInfo = player.shop_info || '{}';
      const tabInfo = player.tab_info || '{}';
      
      await mariadbConnection.execute(
        `INSERT INTO players (id, name, roller_info, shop_info, tab_info, pw, pw_hash, created_at, updated_at, requisition_points, renown_level) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         roller_info = VALUES(roller_info), 
         shop_info = VALUES(shop_info), 
         tab_info = VALUES(tab_info), 
         pw = VALUES(pw), 
         pw_hash = VALUES(pw_hash), 
         updated_at = VALUES(updated_at),
         requisition_points = VALUES(requisition_points),
         renown_level = VALUES(renown_level)`,
        [
          player.id,
          player.name,
          rollerInfo,
          shopInfo,
          tabInfo,
          player.pw || '',
          player.pw_hash || '',
          convertDateTime(player.created_at),
          convertDateTime(player.updated_at),
          player.requisition_points || 0,
          player.renown_level || 'None'
        ]
      );
    }
    
    // Migrate sessions table
    console.log('Migrating sessions table...');
    const sessions = sqliteDb.prepare('SELECT * FROM sessions').all();
    console.log(`Found ${sessions.length} sessions to migrate`);
    
    for (const session of sessions) {
      console.log(`  Migrating session: ${session.session_id}`);
      
      await mariadbConnection.execute(
        `INSERT INTO sessions (id, session_id, data, expires_at, created_at, updated_at) 
         VALUES (?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         data = VALUES(data), 
         expires_at = VALUES(expires_at), 
         updated_at = VALUES(updated_at)`,
        [
          session.id,
          session.session_id,
          session.data || '{}',
          convertDateTime(session.expires_at),
          convertDateTime(session.created_at),
          convertDateTime(session.updated_at)
        ]
      );
    }
    
    // Migrate shop_items table
    console.log('Migrating shop_items table...');
    const shopItems = sqliteDb.prepare('SELECT * FROM shop_items').all();
    console.log(`Found ${shopItems.length} shop items to migrate`);
    
    for (const item of shopItems) {
      console.log(`  Migrating shop item: ${item.name}`);
      
      await mariadbConnection.execute(
        `INSERT INTO shop_items (id, name, category, requisition_cost, renown_requirement, item_type, stats, source, created_at, updated_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         name = VALUES(name),
         category = VALUES(category),
         requisition_cost = VALUES(requisition_cost),
         renown_requirement = VALUES(renown_requirement),
         item_type = VALUES(item_type),
         stats = VALUES(stats),
         source = VALUES(source),
         updated_at = VALUES(updated_at)`,
        [
          item.id,
          item.name,
          item.category,
          item.requisition_cost,
          item.renown_requirement,
          item.item_type,
          item.stats,
          item.source,
          convertDateTime(item.created_at),
          convertDateTime(item.updated_at)
        ]
      );
    }
    
    // Migrate player_inventory table
    console.log('Migrating player_inventory table...');
    const playerInventory = sqliteDb.prepare('SELECT * FROM player_inventory').all();
    console.log(`Found ${playerInventory.length} inventory items to migrate`);
    
    for (const invItem of playerInventory) {
      console.log(`  Migrating inventory item for player ${invItem.player_id}`);
      
      await mariadbConnection.execute(
        `INSERT INTO player_inventory (id, player_id, item_id, quantity, acquired_at, transaction_details) 
         VALUES (?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         quantity = VALUES(quantity),
         transaction_details = VALUES(transaction_details)`,
        [
          invItem.id,
          invItem.player_id,
          invItem.item_id,
          invItem.quantity,
          convertDateTime(invItem.acquired_at),
          invItem.transaction_details
        ]
      );
    }
    
    // Migrate transactions table
    console.log('Migrating transactions table...');
    const transactions = sqliteDb.prepare('SELECT * FROM transactions').all();
    console.log(`Found ${transactions.length} transactions to migrate`);
    
    for (const transaction of transactions) {
      console.log(`  Migrating transaction ${transaction.id}`);
      
      await mariadbConnection.execute(
        `INSERT INTO transactions (id, player_id, item_id, requisition_cost, previous_rp, new_rp, transaction_date) 
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          transaction.id,
          transaction.player_id,
          transaction.item_id,
          transaction.requisition_cost,
          transaction.previous_rp,
          transaction.new_rp,
          convertDateTime(transaction.transaction_date)
        ]
      );
    }
    
    // Migrate armour table
    console.log('Migrating armour table...');
    const armour = sqliteDb.prepare('SELECT * FROM armour').all();
    console.log(`Found ${armour.length} armour items to migrate`);
    
    for (const armourItem of armour) {
      console.log(`  Migrating armour: ${armourItem.name}`);
      
      await mariadbConnection.execute(
        `INSERT INTO armour (id, name, req, renown, category, stats, source, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         req = VALUES(req),
         renown = VALUES(renown),
         category = VALUES(category),
         stats = VALUES(stats),
         source = VALUES(source)`,
        [
          armourItem.id,
          armourItem.name,
          armourItem.req,
          armourItem.renown,
          armourItem.category,
          armourItem.stats,
          armourItem.source,
          convertDateTime(armourItem.created_at)
        ]
      );
    }
    
    // Migrate weapons table
    console.log('Migrating weapons table...');
    const weapons = sqliteDb.prepare('SELECT * FROM weapons').all();
    console.log(`Found ${weapons.length} weapons to migrate`);
    
    for (const weapon of weapons) {
      console.log(`  Migrating weapon: ${weapon.name}`);
      
      await mariadbConnection.execute(
        `INSERT INTO weapons (id, name, req, renown, category, stats, source, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         req = VALUES(req),
         renown = VALUES(renown),
         category = VALUES(category),
         stats = VALUES(stats),
         source = VALUES(source)`,
        [
          weapon.id,
          weapon.name,
          weapon.req,
          weapon.renown,
          weapon.category,
          weapon.stats,
          weapon.source,
          convertDateTime(weapon.created_at)
        ]
      );
    }
    
    // Migrate bestiary table
    console.log('Migrating bestiary table...');
    const bestiary = sqliteDb.prepare('SELECT * FROM bestiary').all();
    console.log(`Found ${bestiary.length} bestiary entries to migrate`);
    
    for (const beast of bestiary) {
      console.log(`  Migrating bestiary: ${beast.name}`);
      
      await mariadbConnection.execute(
        `INSERT INTO bestiary (id, name, book, page, pdf, stats, profile, snippet, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         book = VALUES(book),
         page = VALUES(page),
         pdf = VALUES(pdf),
         stats = VALUES(stats),
         profile = VALUES(profile),
         snippet = VALUES(snippet)`,
        [
          beast.id,
          beast.name,
          beast.book,
          beast.page,
          beast.pdf,
          beast.stats,
          beast.profile,
          beast.snippet,
          convertDateTime(beast.created_at)
        ]
      );
    }
    
    // Migrate rules table
    console.log('Migrating rules table...');
    const rules = sqliteDb.prepare('SELECT * FROM rules').all();
    console.log(`Found ${rules.length} rules to migrate`);
    
    for (const rule of rules) {
      console.log(`  Migrating rule: ${rule.title}`);
      
      // Truncate rule_id if it's too long (max 255 chars)
      const ruleId = rule.rule_id ? rule.rule_id.substring(0, 255) : null;
      // Truncate title if it's too long (max 500 chars)
      const title = rule.title ? rule.title.substring(0, 500) : null;
      
      await mariadbConnection.execute(
        `INSERT INTO rules (id, rule_id, title, content, page, source, source_abbr, category, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         title = VALUES(title),
         content = VALUES(content),
         page = VALUES(page),
         source = VALUES(source),
         source_abbr = VALUES(source_abbr),
         category = VALUES(category)`,
        [
          rule.id,
          ruleId,
          title,
          rule.content,
          rule.page,
          rule.source,
          rule.source_abbr,
          rule.category,
          convertDateTime(rule.created_at)
        ]
      );
    }
    
    // Migrate rules_staging table
    console.log('Migrating rules_staging table...');
    const rulesStaging = sqliteDb.prepare('SELECT * FROM rules_staging').all();
    console.log(`Found ${rulesStaging.length} rules_staging entries to migrate`);
    
    for (const rule of rulesStaging) {
      console.log(`  Migrating rules_staging: ${rule.title}`);
      
      await mariadbConnection.execute(
        `INSERT INTO rules_staging (id, title, content, category, page, original_json, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE 
         title = VALUES(title), 
         content = VALUES(content), 
         category = VALUES(category), 
         page = VALUES(page), 
         original_json = VALUES(original_json)`,
        [
          rule.id,
          rule.title,
          rule.content,
          rule.category,
          rule.page,
          rule.original_json,
          convertDateTime(rule.created_at)
        ]
      );
    }
    
    console.log('Migration completed successfully!');
    
    // Verify migration
    console.log('\nVerifying migration...');
    const [mariadbPlayers] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM players');
    const [mariadbSessions] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM sessions');
    const [mariadbShopItems] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM shop_items');
    const [mariadbInventory] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM player_inventory');
    const [mariadbTransactions] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM transactions');
    const [mariadbArmour] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM armour');
    const [mariadbWeapons] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM weapons');
    const [mariadbBestiary] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM bestiary');
    const [mariadbRules] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM rules');
    const [mariadbRulesStaging] = await mariadbConnection.execute('SELECT COUNT(*) as count FROM rules_staging');
    
    console.log(`MariaDB players: ${mariadbPlayers[0].count}`);
    console.log(`MariaDB sessions: ${mariadbSessions[0].count}`);
    console.log(`MariaDB shop_items: ${mariadbShopItems[0].count}`);
    console.log(`MariaDB player_inventory: ${mariadbInventory[0].count}`);
    console.log(`MariaDB transactions: ${mariadbTransactions[0].count}`);
    console.log(`MariaDB armour: ${mariadbArmour[0].count}`);
    console.log(`MariaDB weapons: ${mariadbWeapons[0].count}`);
    console.log(`MariaDB bestiary: ${mariadbBestiary[0].count}`);
    console.log(`MariaDB rules: ${mariadbRules[0].count}`);
    console.log(`MariaDB rules_staging: ${mariadbRulesStaging[0].count}`);
    
  } catch (error) {
    console.error('Migration failed:', error);
    process.exit(1);
  } finally {
    if (sqliteDb) {
      sqliteDb.close();
    }
    if (mariadbConnection) {
      await mariadbConnection.end();
    }
  }
}

// Run migration
migrateData().catch(console.error);
