import mysql from 'mysql2/promise';
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { development } from '../config.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Load .env from backend directory
dotenv.config({ path: join(__dirname, '..', '.env') });

const report = [];

const dbConfig = {
  host: process.env.DB_HOST || development.host || 'localhost',
  user: process.env.DB_USER || development.username || 'root',
  password: process.env.DB_PASSWORD || development.password || '',
  database: process.env.DB_NAME || development.database || 'trainingdiary',
};

async function getTables(connection) {
  const [rows] = await connection.execute(
    `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_TYPE='BASE TABLE'`,
    [dbConfig.database]
  );
  return rows.map(r => r.TABLE_NAME);
}

async function getIndexSummary(connection, table) {
  const [rows] = await connection.execute(`SHOW INDEX FROM \`${table}\``);
  const byName = rows.reduce((acc, r) => {
    const key = r.Key_name;
    if (!acc[key]) acc[key] = { nonUnique: r.Non_unique === 1, seqMap: {}, columns: [] };
    acc[key].seqMap[r.Seq_in_index] = r.Column_name;
    return acc;
  }, {});
  // normalize columns order by seq
  for (const name of Object.keys(byName)) {
    const cols = Object.keys(byName[name].seqMap)
      .sort((a, b) => Number(a) - Number(b))
      .map(k => byName[name].seqMap[k]);
    byName[name].columns = cols;
  }
  return byName;
}

async function cleanupDuplicates(connection, table) {
  const before = await getIndexSummary(connection, table);
  const keepSignatureToName = new Map();
  const dropNames = [];

  for (const [name, info] of Object.entries(before)) {
    if (name === 'PRIMARY') continue; // niemals Primary droppen
    const uniqueFlag = info.nonUnique ? 'N' : 'U';
    const sig = `${uniqueFlag}|${info.columns.join(',')}`;
    if (!keepSignatureToName.has(sig)) {
      keepSignatureToName.set(sig, name);
    } else {
      // doppelter Index mit gleicher Spaltenliste und gleicher Einzigartigkeit
      dropNames.push(name);
    }
  }

  for (const idxName of dropNames) {
    try {
      await connection.execute(`DROP INDEX \`${idxName}\` ON \`${table}\``);
      report.push(`[drop] ${table}: ${idxName}`);
    } catch (e) {
      report.push(`[warn] ${table}: konnte Index ${idxName} nicht löschen: ${e.code || e.message}`);
    }
  }

  const after = await getIndexSummary(connection, table);
  return { beforeCount: Object.keys(before).length, afterCount: Object.keys(after).length, dropped: dropNames.length };
}

async function main() {
  let connection;
  try {
    report.push(`Connecting to DB: ${JSON.stringify(dbConfig)}`);
    connection = await mysql.createConnection(dbConfig);

    const tables = await getTables(connection);
    report.push(`Found ${tables.length} tables`);

    let totalBefore = 0;
    let totalAfter = 0;
    let totalDropped = 0;

    for (const table of tables) {
      const { beforeCount, afterCount, dropped } = await cleanupDuplicates(connection, table);
      totalBefore += beforeCount;
      totalAfter += afterCount;
      totalDropped += dropped;
    }

    report.push(`Summary: ${JSON.stringify({ totalBefore, totalAfter, totalDropped })}`);
  } catch (e) {
    console.error('Cleanup failed:', e);
    process.exitCode = 1;
  } finally {
    if (connection) await connection.end();
    if (report.length > 0) {
      process.stdout.write(`${report.join('\n')}\n`);
    }
  }
}

main();


