const mysql = require('mysql2/promise');
require('dotenv').config();

async function main() {
  console.log('Comparing database structures between "igcrm" (local) and "crmlive1" (live)...');

  // Parse credentials from local DATABASE_URL or default to root@127.0.0.1:3306
  let connectionConfig = {
    host: '127.0.0.1',
    port: 3306,
    user: 'root',
    password: '',
  };

  const dbUrl = process.env.DATABASE_URL;
  if (dbUrl) {
    try {
      const url = dbUrl.replace('mysql://', '');
      const [auth, hostPortDb] = url.split('@');
      const [user, password] = auth.split(':');
      const [hostPort, database] = hostPortDb.split('/');
      const [host, port] = hostPort.split(':');
      connectionConfig.user = user;
      connectionConfig.password = password || '';
      connectionConfig.host = host;
      connectionConfig.port = parseInt(port) || 3306;
    } catch (e) {
      console.log('Error parsing DATABASE_URL, using defaults.');
    }
  }

  console.log(`Connecting to MySQL on ${connectionConfig.host}:${connectionConfig.port}...`);

  try {
    const connection = await mysql.createConnection(connectionConfig);
    console.log('Connected successfully!');

    // Check if databases exist
    const [dbs] = await connection.query('SHOW DATABASES');
    const dbNames = dbs.map(d => d.Database);
    
    const localDb = 'igcrm';
    const liveDb = 'crmlive1';

    if (!dbNames.includes(localDb)) {
      console.error(`Local database "${localDb}" not found! Available databases:`, dbNames);
      await connection.end();
      return;
    }
    if (!dbNames.includes(liveDb)) {
      console.error(`Live database "${liveDb}" not found! Available databases:`, dbNames);
      await connection.end();
      return;
    }

    console.log(`Querying information_schema for ${localDb} and ${liveDb}...`);

    // Fetch column definitions for local
    const [localCols] = await connection.query(`
      SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_KEY
      FROM information_schema.columns
      WHERE TABLE_SCHEMA = ?
      ORDER BY TABLE_NAME, ORDINAL_POSITION
    `, [localDb]);

    // Fetch column definitions for live
    const [liveCols] = await connection.query(`
      SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_KEY
      FROM information_schema.columns
      WHERE TABLE_SCHEMA = ?
      ORDER BY TABLE_NAME, ORDINAL_POSITION
    `, [liveDb]);

    await connection.end();

    // Map columns to structured objects
    const localSchema = {};
    localCols.forEach(col => {
      if (!localSchema[col.TABLE_NAME]) localSchema[col.TABLE_NAME] = {};
      localSchema[col.TABLE_NAME][col.COLUMN_NAME] = col;
    });

    const liveSchema = {};
    liveCols.forEach(col => {
      if (!liveSchema[col.TABLE_NAME]) liveSchema[col.TABLE_NAME] = {};
      liveSchema[col.TABLE_NAME][col.COLUMN_NAME] = col;
    });

    console.log('\n--- SCHEMA COMPARISON RESULTS ---\n');

    // 1. Check for missing tables
    const localTables = Object.keys(localSchema);
    const liveTables = Object.keys(liveSchema);

    const missingInLive = localTables.filter(t => !liveTables.includes(t));
    const extraInLive = liveTables.filter(t => !localTables.includes(t));

    if (missingInLive.length > 0) {
      console.log(`❌ Tables in Local (${localDb}) but missing in Live (${liveDb}):`, missingInLive);
    }
    if (extraInLive.length > 0) {
      console.log(`ℹ️ Tables in Live (${liveDb}) but missing in Local (${localDb}) (pre-existing/extra):`, extraInLive);
    }

    // 2. Compare shared tables
    const sharedTables = localTables.filter(t => liveTables.includes(t));
    let differencesFound = false;

    sharedTables.forEach(tableName => {
      const localTab = localSchema[tableName];
      const liveTab = liveSchema[tableName];

      const localColsList = Object.keys(localTab);
      const liveColsList = Object.keys(liveTab);

      const missingColsInLive = localColsList.filter(c => !liveColsList.includes(c));
      const extraColsInLive = liveColsList.filter(c => !localColsList.includes(c));

      let tableDiffHeaderPrinted = false;
      const printTableDiffHeader = () => {
        if (!tableDiffHeaderPrinted) {
          console.log(`\nTable: "${tableName}"`);
          tableDiffHeaderPrinted = true;
          differencesFound = true;
        }
      };

      if (missingColsInLive.length > 0) {
        printTableDiffHeader();
        console.log(`  ❌ Columns in Local but MISSING in Live:`, missingColsInLive);
      }
      if (extraColsInLive.length > 0) {
        printTableDiffHeader();
        console.log(`  ℹ️ Columns in Live but MISSING in Local:`, extraColsInLive);
      }

      // Compare details of shared columns
      const sharedCols = localColsList.filter(c => liveColsList.includes(c));
      sharedCols.forEach(colName => {
        const localCol = localTab[colName];
        const liveCol = liveTab[colName];

        const typeDiff = localCol.COLUMN_TYPE !== liveCol.COLUMN_TYPE;
        const nullDiff = localCol.IS_NULLABLE !== liveCol.IS_NULLABLE;
        const defaultDiff = localCol.COLUMN_DEFAULT !== liveCol.COLUMN_DEFAULT;
        const keyDiff = localCol.COLUMN_KEY !== liveCol.COLUMN_KEY;

        if (typeDiff || nullDiff || defaultDiff || keyDiff) {
          printTableDiffHeader();
          console.log(`  Column: "${colName}" has differences:`);
          if (typeDiff) console.log(`    - Type: Local="${localCol.COLUMN_TYPE}", Live="${liveCol.COLUMN_TYPE}"`);
          if (nullDiff) console.log(`    - Nullable: Local="${localCol.IS_NULLABLE}", Live="${liveCol.IS_NULLABLE}"`);
          if (defaultDiff) console.log(`    - Default: Local="${localCol.COLUMN_DEFAULT}", Live="${liveCol.COLUMN_DEFAULT}"`);
          if (keyDiff) console.log(`    - Key: Local="${localCol.COLUMN_KEY}", Live="${liveCol.COLUMN_KEY}"`);
        }
      });
    });

    if (!differencesFound && missingInLive.length === 0 && extraInLive.length === 0) {
      console.log('✅ Local and Live schemas are identical!');
    }

  } catch (error) {
    console.error('Comparison failed:', error);
  }
}

main();
