import { QueryInterface, QueryTypes } from 'sequelize';
import { initializeGoogleSecretManager } from '../services/googleSecretManager.service';
import * as m0 from '../migrations/2025103000-create-users';
import * as m1 from '../migrations/2025103001-create-workflow-requests';
import * as m2 from '../migrations/2025103002-create-approval-levels';
import * as m3 from '../migrations/2025103003-create-participants';
import * as m4 from '../migrations/2025103004-create-documents';
import * as m5 from '../migrations/20251031_01_create_subscriptions';
import * as m6 from '../migrations/20251031_02_create_activities';
import * as m7 from '../migrations/20251031_03_create_work_notes';
import * as m8 from '../migrations/20251031_04_create_work_note_attachments';
import * as m9 from '../migrations/20251104-add-tat-alert-fields';
import * as m10 from '../migrations/20251104-create-tat-alerts';
import * as m11 from '../migrations/20251104-create-kpi-views';
import * as m12 from '../migrations/20251104-create-holidays';
import * as m13 from '../migrations/20251104-create-admin-config';
import * as m14 from '../migrations/20251105-add-skip-fields-to-approval-levels';
import * as m15 from '../migrations/2025110501-alter-tat-days-to-generated';
import * as m16 from '../migrations/20251111-create-notifications';
import * as m17 from '../migrations/20251111-create-conclusion-remarks';
import * as m18 from '../migrations/20251118-add-breach-reason-to-approval-levels';
import * as m19 from '../migrations/20251121-add-ai-model-configs';
import * as m20 from '../migrations/20250122-create-request-summaries';
import * as m21 from '../migrations/20250122-create-shared-summaries';
import * as m22 from '../migrations/20250123-update-request-number-format';
import * as m23 from '../migrations/20250126-add-paused-to-enum';
import * as m24 from '../migrations/20250126-add-paused-to-workflow-status-enum';
import * as m25 from '../migrations/20250126-add-pause-fields-to-workflow-requests';
import * as m26 from '../migrations/20250126-add-pause-fields-to-approval-levels';
import * as m27 from '../migrations/20250127-migrate-in-progress-to-pending';
// Base branch migrations (m28-m29)
import * as m28 from '../migrations/20250130-migrate-to-vertex-ai';
import * as m29 from '../migrations/20251203-add-user-notification-preferences';
// Dealer claim branch migrations (m30-m39)
import * as m30 from '../migrations/20251210-add-workflow-type-support';
import * as m31 from '../migrations/20251210-enhance-workflow-templates';
import * as m32 from '../migrations/20251210-add-template-id-foreign-key';
import * as m33 from '../migrations/20251210-create-dealer-claim-tables';
import * as m34 from '../migrations/20251210-create-proposal-cost-items-table';
import * as m35 from '../migrations/20251211-create-internal-orders-table';
import * as m36 from '../migrations/20251211-create-claim-budget-tracking-table';
import * as m37 from '../migrations/20251213-drop-claim-details-invoice-columns';
import * as m38 from '../migrations/20251213-create-claim-invoice-credit-note-tables';
import * as m39 from '../migrations/20251214-create-dealer-completion-expenses';
import * as m40 from '../migrations/20251218-fix-claim-invoice-credit-note-columns';
import * as m41 from '../migrations/20250120-create-dealers-table';
import * as m42 from '../migrations/20250125-create-activity-types';
import * as m43 from '../migrations/20260113-redesign-dealer-claim-history';
import * as m44 from '../migrations/20260123-fix-template-id-schema';
import * as m45 from '../migrations/20260209-add-gst-and-pwc-fields';
import * as m46 from '../migrations/20260210-add-raw-pwc-responses';
import * as m47 from '../migrations/20260216-create-api-tokens';
import * as m48 from '../migrations/20260216-add-qty-hsn-to-expenses';
import * as m47a from '../migrations/20260217-add-is-service-to-expenses';
import * as m48a from '../migrations/20260217-create-claim-invoice-items';
import * as m49 from '../migrations/20260302-refine-dealer-claim-schema';
import * as m50 from '../migrations/20260220-create-form16-tables';
import * as m51 from '../migrations/20260220000001-add-form16-ocr-extracted-data';
import * as m52 from '../migrations/20260222000001-create-tds-26as-entries';
import * as m53 from '../migrations/20260223000001-create-form-16-debit-notes';
import * as m54 from '../migrations/20260224000001-create-form-16-26as-upload-log';
import * as m55 from '../migrations/20260225000001-add-form16-26as-upload-log-id-and-tables';
import * as m56 from '../migrations/20260225000001-create-form16-non-submitted-notifications';
import * as m57 from '../migrations/20260225100001-add-form16-archived-at';
import * as m58 from '../migrations/20260303100001-drop-form16a-number-unique';
import * as m59 from '../migrations/20260309-add-wfm-push-fields';
import * as m60 from '../migrations/20260316-update-holiday-type-enum';
import * as m61 from '../migrations/20260317-refactor-activity-types-columns';
import * as m62 from '../migrations/20260317100001-create-form16-sap-responses';
import * as m63 from '../migrations/20260317120001-add-form16-trns-uniq-no';
import * as m64 from '../migrations/20260318100001-create-form16-debit-note-sap-responses';
import * as m65 from '../migrations/20260318200001-add-sap-response-csv-fields';
import * as m66 from '../migrations/20260324090001-refactor-form16-sap-response-and-add-read-log';
import * as m67 from '../migrations/20260324110001-add-pan-number-to-26as';
import * as m68 from '../migrations/20260325090001-ensure-pan-number-in-26as';
import * as m69 from '../migrations/20260325094500-add-user-session-and-hsn-sac-codes';
import * as m70 from '../migrations/20260325175000-update-credit-notes-and-add-items';
import * as m71 from '../migrations/2026041300-create-cpc-cdc-tables';
import * as m72 from '../migrations/20260414100000-ensure-cpc-cdc-tables-exist';
import * as m73 from '../migrations/20260416120000-rename-cpc-cdc-admin-config-key';


interface Migration {
  name: string;
  module: any;
}

// Define ALL migrations in order. Required for fresh DB (e.g. UAT/production).
// Order matters: base tables first, then tables that reference them.
const migrations: Migration[] = [
  { name: '2025103000-create-users', module: m0 },
  { name: '2025103001-create-workflow-requests', module: m1 },
  { name: '2025103002-create-approval-levels', module: m2 },
  { name: '2025103003-create-participants', module: m3 },
  { name: '2025103004-create-documents', module: m4 },
  { name: '20251031_01_create_subscriptions', module: m5 },
  { name: '20251031_02_create_activities', module: m6 },
  { name: '20251031_03_create_work_notes', module: m7 },
  { name: '20251031_04_create_work_note_attachments', module: m8 },
  { name: '20251104-add-tat-alert-fields', module: m9 },
  { name: '20251104-create-tat-alerts', module: m10 },
  { name: '20251104-create-kpi-views', module: m11 },
  { name: '20251104-create-holidays', module: m12 },
  { name: '20251104-create-admin-config', module: m13 },
  { name: '20251105-add-skip-fields-to-approval-levels', module: m14 },
  { name: '2025110501-alter-tat-days-to-generated', module: m15 },
  { name: '20251111-create-notifications', module: m16 },
  { name: '20251111-create-conclusion-remarks', module: m17 },
  { name: '20251118-add-breach-reason-to-approval-levels', module: m18 },
  { name: '20251121-add-ai-model-configs', module: m19 },
  { name: '20250122-create-request-summaries', module: m20 },
  { name: '20250122-create-shared-summaries', module: m21 },
  { name: '20250123-update-request-number-format', module: m22 },
  { name: '20250126-add-paused-to-enum', module: m23 },
  { name: '20250126-add-paused-to-workflow-status-enum', module: m24 },
  { name: '20250126-add-pause-fields-to-workflow-requests', module: m25 },
  { name: '20250126-add-pause-fields-to-approval-levels', module: m26 },
  { name: '20250127-migrate-in-progress-to-pending', module: m27 },
  { name: '20250130-migrate-to-vertex-ai', module: m28 },
  { name: '20251203-add-user-notification-preferences', module: m29 },
  { name: '20251210-add-workflow-type-support', module: m30 },
  { name: '20251210-enhance-workflow-templates', module: m31 },
  { name: '20251210-add-template-id-foreign-key', module: m32 },
  { name: '20251210-create-dealer-claim-tables', module: m33 },
  { name: '20251210-create-proposal-cost-items-table', module: m34 },
  { name: '20251211-create-internal-orders-table', module: m35 },
  { name: '20251211-create-claim-budget-tracking-table', module: m36 },
  { name: '20251213-drop-claim-details-invoice-columns', module: m37 },
  { name: '20251213-create-claim-invoice-credit-note-tables', module: m38 },
  { name: '20251214-create-dealer-completion-expenses', module: m39 },
  { name: '20251218-fix-claim-invoice-credit-note-columns', module: m40 },
  { name: '20250120-create-dealers-table', module: m41 },
  { name: '20250125-create-activity-types', module: m42 },
  { name: '20260113-redesign-dealer-claim-history', module: m43 },
  { name: '20260123-fix-template-id-schema', module: m44 },
  { name: '20260209-add-gst-and-pwc-fields', module: m45 },
  { name: '20260210-add-raw-pwc-responses', module: m46 },
  { name: '20260216-create-api-tokens', module: m47 },
  { name: '20260216-add-qty-hsn-to-expenses', module: m48 },
  { name: '20260217-add-is-service-to-expenses', module: m47a },
  { name: '20260217-create-claim-invoice-items', module: m48a },
  { name: '20260302-refine-dealer-claim-schema', module: m49 },
  { name: '20260220-create-form16-tables', module: m50 },
  { name: '20260220000001-add-form16-ocr-extracted-data', module: m51 },
  { name: '20260222000001-create-tds-26as-entries', module: m52 },
  { name: '20260223000001-create-form-16-debit-notes', module: m53 },
  { name: '20260224000001-create-form-16-26as-upload-log', module: m54 },
  { name: '20260225000001-add-form16-26as-upload-log-id-and-tables', module: m55 },
  { name: '20260225000001-create-form16-non-submitted-notifications', module: m56 },
  { name: '20260225100001-add-form16-archived-at', module: m57 },
  { name: '20260303100001-drop-form16a-number-unique', module: m58 },
  { name: '20260309-add-wfm-push-fields', module: m59 },
  { name: '20260316-update-holiday-type-enum', module: m60 },
  { name: '20260317-refactor-activity-types-columns', module: m61 },
  { name: '20260317100001-create-form16-sap-responses', module: m62 },
  { name: '20260317120001-add-form16-trns-uniq-no', module: m63 },
  { name: '20260318100001-create-form16-debit-note-sap-responses', module: m64 },
  { name: '20260318200001-add-sap-response-csv-fields', module: m65 },
  { name: '20260324090001-refactor-form16-sap-response-and-add-read-log', module: m66 },
  { name: '20260324110001-add-pan-number-to-26as', module: m67 },
  { name: '20260325090001-ensure-pan-number-in-26as', module: m68 },
  { name: '20260325094500-add-user-session-and-hsn-sac-codes', module: m69 },
  { name: '20260325175000-update-credit-notes-and-add-items', module: m70 },
  { name: '2026041300-create-cpc-cdc-tables', module: m71 },
  { name: '20260414100000-ensure-cpc-cdc-tables-exist', module: m72 },
  { name: '20260416120000-rename-cpc-cdc-admin-config-key', module: m73 },
];

/**
 * Create migrations tracking table if it doesn't exist
 */
async function ensureMigrationsTable(queryInterface: QueryInterface): Promise<void> {
  try {
    const tables = await queryInterface.showAllTables();

    const tableName = (t: string) => (typeof t === 'string' ? t.toLowerCase() : (t as any));
    if (!tables.some((t: string) => tableName(t) === 'migrations')) {
      await queryInterface.sequelize.query(`
        CREATE TABLE IF NOT EXISTS migrations (
          id SERIAL PRIMARY KEY,
          name VARCHAR(255) NOT NULL UNIQUE,
          executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
      `);
      // Migrations table created
    }
  } catch (error) {
    console.error('Error creating migrations table:', error);
    throw error;
  }
}

/**
 * Get list of already executed migrations
 */
async function getExecutedMigrations(sequelize: any): Promise<string[]> {
  try {
    const results = await sequelize.query(
      'SELECT name FROM migrations ORDER BY id',
      { type: QueryTypes.SELECT }
    ) as { name: string }[];
    return results.map(r => r.name);
  } catch (error) {
    // Table might not exist yet
    return [];
  }
}

/**
 * Mark migration as executed
 */
async function markMigrationExecuted(sequelize: any, name: string): Promise<void> {
  await sequelize.query(
    'INSERT INTO migrations (name) VALUES (:name) ON CONFLICT (name) DO NOTHING',
    {
      replacements: { name },
      type: QueryTypes.INSERT
    }
  );
}

/**
 * Run all pending migrations
 */
export async function runMigrations() {
  try {
    console.log('🔐 Initializing secrets...');
    await initializeGoogleSecretManager();

    // Dynamically import sequelize after secrets are loaded
    const { sequelize } = require('../config/database');

    await sequelize.authenticate();

    const queryInterface = sequelize.getQueryInterface();

    // Ensure migrations tracking table exists
    await ensureMigrationsTable(queryInterface);

    // Get already executed migrations
    const executedMigrations = await getExecutedMigrations(sequelize);

    // Find pending migrations
    const pendingMigrations = migrations.filter(
      m => !executedMigrations.includes(m.name)
    );

    if (pendingMigrations.length === 0) {
      console.log('✅ Migrations up-to-date');
      return;
    }

    console.log(`🔄 Running ${pendingMigrations.length} migration(s)...`);


    // Run each pending migration
    for (const migration of pendingMigrations) {
      try {
        await migration.module.up(queryInterface);
        await markMigrationExecuted(sequelize, migration.name);
        console.log(`✅ ${migration.name}`);
      } catch (error: any) {
        console.error(`❌ Migration failed: ${migration.name} - ${error.message}`);
        throw error;
      }
    }

    console.log(`✅ Applied ${pendingMigrations.length} migration(s)`);
  } catch (err: any) {
    console.error('❌ Migration failed:', err.message);
    throw err;
  }
}

// When executed directly: behave like a script (set exit codes).
if (require.main === module) {
  runMigrations()
    .then(() => process.exit(0))
    .catch(() => process.exit(1));
}
