/**
 * Automatic Database Setup Script
 * Runs before server starts to ensure database is ready
 * 
 * This script:
 * 1. Checks if database exists
 * 2. Creates database if missing
 * 3. Installs required extensions
 * 4. Runs all pending migrations (checks migrations table to avoid re-running)
 * 5. Configs are auto-seeded by configSeed.service.ts on server start (30 configs)
 */

import fs from 'fs';
import path from 'path';
import dotenv from 'dotenv';

// 1. Initialize dotenv FIRST before any other internal imports
// This ensures that modules imported later (like GoogleSecretManagerService)
// can see the environment variables in their constructor/initialization
const envPath = path.resolve(process.cwd(), '.env');
if (fs.existsSync(envPath)) {
  dotenv.config({ path: envPath });
} else {
  const parentEnvPath = path.resolve(process.cwd(), '..', '.env');
  if (fs.existsSync(parentEnvPath)) {
    dotenv.config({ path: parentEnvPath });
  }
}

// 2. Now import internal modules
import { Client } from 'pg';
import { QueryTypes } from 'sequelize';
import { initializeGoogleSecretManager } from '../services/googleSecretManager.service';
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

async function checkAndCreateDatabase(): Promise<boolean> {
  // DB constants moved inside functions to ensure secrets are loaded first
  const isSSL = (process.env.DB_SSL || '').trim() === 'true';
  const DB_HOST = process.env.DB_HOST || 'localhost';
  const DB_PORT = parseInt(process.env.DB_PORT || '5432');
  const DB_USER = process.env.DB_USER || 'postgres';
  const DB_PASSWORD = typeof process.env.DB_PASSWORD === 'string' ? process.env.DB_PASSWORD : '';
  const DB_NAME = process.env.DB_NAME || 're_workflow_db';

  console.log(`[Setup Debug] DB_HOST: ${DB_HOST}, DB_USER: ${DB_USER}, SSL: ${isSSL}, HasPassword: ${!!DB_PASSWORD}`);

  const client = new Client({
    host: DB_HOST,
    port: DB_PORT,
    user: DB_USER,
    password: DB_PASSWORD,
    database: 'postgres', // Connect to default postgres database
    ssl: isSSL ? { rejectUnauthorized: false } : undefined,
  });

  try {
    await client.connect();
    console.log('🔍 Checking if database exists...');

    // Check if database exists
    const result = await client.query(
      `SELECT 1 FROM pg_database WHERE datname = $1`,
      [DB_NAME]
    );

    if (result.rows.length === 0) {
      console.log(`📦 Database '${DB_NAME}' not found. Creating...`);

      // Create database
      await client.query(`CREATE DATABASE "${DB_NAME}"`);
      console.log(`✅ Database '${DB_NAME}' created successfully!`);

      await client.end();

      // Connect to new database and install extensions
      const newDbClient = new Client({
        host: DB_HOST,
        port: DB_PORT,
        user: DB_USER,
        password: DB_PASSWORD,
        database: DB_NAME,
        ssl: isSSL ? { rejectUnauthorized: false } : undefined,
      });

      await newDbClient.connect();
      console.log('📦 Installing uuid-ossp extension...');
      await newDbClient.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"');
      console.log('✅ Extension installed!');
      await newDbClient.end();

      return true; // Database was created
    } else {
      console.log(`✅ Database '${DB_NAME}' already exists.`);
      await client.end();
      return false; // Database already existed
    }
  } catch (error: any) {
    console.error('❌ Database check/creation failed:', error.message);
    await client.end();
    throw error;
  }
}

async function runMigrations(): Promise<void> {
  try {
    console.log('🔄 Checking and running pending migrations...');

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

    const migrations = [
      { 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 },
      // Base branch migrations (m28-m29)
      { name: '20250130-migrate-to-vertex-ai', module: m28 },
      { name: '20251203-add-user-notification-preferences', module: m29 },
      // Dealer claim branch migrations (m30-m39)
      { 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 },
    ];

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

    // Ensure migrations tracking table exists (case-insensitive for PostgreSQL)
    const tables = await queryInterface.showAllTables();
    const tableName = (t: string | { tableName?: string }) => (typeof t === 'string' ? t.toLowerCase() : (t && t.tableName ? String(t.tableName).toLowerCase() : ''));
    if (!tables.some((t: string | { tableName?: 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
        )
      `);
    }

    // Get already executed migrations
    const executedResults = await sequelize.query(
      'SELECT name FROM migrations ORDER BY id',
      { type: QueryTypes.SELECT }
    ) as { name: string }[];
    const executedMigrations = executedResults.map(r => r.name);

    // 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} pending migration(s)...`);

    // Run each pending migration
    for (const migration of pendingMigrations) {
      try {
        console.log(`  → ${migration.name}`);

        // Call the up function - works for both module.exports and export styles
        await migration.module.up(queryInterface);

        // Mark as executed
        await sequelize.query(
          'INSERT INTO migrations (name) VALUES (:name) ON CONFLICT (name) DO NOTHING',
          {
            replacements: { name: migration.name },
            type: QueryTypes.INSERT
          }
        );
        console.log(`  ✅ ${migration.name}`);
      } catch (error: any) {
        console.error(`  ❌ ${migration.name} failed: ${error.message}`);
        throw error;
      }
    }

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

async function testConnection(): Promise<void> {
  try {
    console.log('🔌 Testing database connection...');
    const { sequelize } = require('../config/database');
    await sequelize.authenticate();
    console.log('✅ Database connection established!');
  } catch (error: any) {
    console.error('❌ Unable to connect to database:', error.message);
    throw error;
  }
}

async function autoSetup(): Promise<void> {
  console.log('\n========================================');
  console.log('🚀 Royal Enfield Workflow - Auto Setup');
  console.log('========================================\n');

  try {
    // Step 0: Initialize secrets
    console.log('🔐 Initializing secrets...');
    await initializeGoogleSecretManager();
    const appDomain = process.env.APP_DOMAIN || 'royalenfield.com';

    // Step 1: Check and create database if needed
    const wasCreated = await checkAndCreateDatabase();

    // Step 2: Test connection
    await testConnection();

    // Step 3: Run migrations (always, to catch any pending migrations)
    await runMigrations();

    console.log('\n========================================');
    console.log('✅ Setup completed successfully!');
    console.log('========================================\n');

    console.log('📝 Note: Admin configurations will be auto-seeded on server start if table is empty.');
    console.log('📝 Note: Dealers table will be empty - import dealers using CSV import script.\n');


    console.log('📝 Note: Admin configurations will be auto-seeded on server start if table is empty.\n');

    if (wasCreated) {
      console.log('💡 Next steps:');
      console.log('   1. Server will start automatically');
      console.log('   2. Log in via SSO');
      console.log('   3. Run this SQL to make yourself admin:');
      console.log(`      UPDATE users SET role = 'ADMIN' WHERE email = 'your-email@${appDomain}';\n`);
    }

  } catch (error: any) {
    console.error('\n========================================');
    console.error('❌ Setup failed!');
    console.error('========================================');
    console.error('Error:', error.message);
    console.error('\nPlease check:');
    console.error('1. PostgreSQL is running');
    console.error('2. DB credentials in .env are correct');
    console.error('3. User has permission to create databases\n');
    process.exit(1);
  }
}

// Run if called directly
if (require.main === module) {
  autoSetup().then(() => {
    process.exit(0);
  }).catch(() => {
    process.exit(1);
  });
}

export default autoSetup;

