import dotenv from 'dotenv';
import fs from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { Pool } from 'pg';

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

// Load environment variables
dotenv.config({ path: join(__dirname, '..', '.env') });

// Database configuration
const dbConfig = {
  host: process.env.LOCAL_DB_HOST || '192.168.8.151',
  port: parseInt(process.env.LOCAL_DB_PORT || '5432'),
  user: process.env.LOCAL_DB_USER || 'postgres',
  password: process.env.LOCAL_DB_PASSWORD || 'postgres',
  database: process.env.LOCAL_DB_NAME || 'institutional_trader'
};

/**
 * Execute SQL file or query
 */
async function executeSQL(query, params = []) {
  const pool = new Pool(dbConfig);
  
  try {
    const result = await pool.query(query, params);
    return result.rows;
  } finally {
    await pool.end();
  }
}

/**
 * Run analysis queries to show current state
 */
async function analyzeDatabase() {
  console.log('\n📊 Analyzing database date/time formats...\n');
  
  const queries = {
    'CreatedDate Analysis': `
      SELECT 
        COUNT(*) FILTER (WHERE "CreatedDate"::text ~ '^\\d{4}-\\d{2}-\\d{2}$') as valid_iso_date,
        COUNT(*) FILTER (WHERE "CreatedDate"::text ~ '^\\d{1,2}/\\d{1,2}/\\d{2,4}$') as slash_format,
        COUNT(*) FILTER (WHERE "CreatedDate" IS NOT NULL AND "CreatedDate"::text !~ '^\\d{4}-\\d{2}-\\d{2}$' AND "CreatedDate"::text !~ '^\\d{1,2}/\\d{1,2}/\\d{2,4}$') as invalid_format,
        COUNT(*) FILTER (WHERE "CreatedDate" IS NULL) as null_dates,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `,
    
    'CreatedTime Analysis': `
      SELECT 
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}:\\d{2}\\s+[AP]M$') as valid_with_space,
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}:\\d{2}[AP]M$') as valid_no_space,
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}\\s+[AP]M$') as valid_minutes_only_space,
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}[AP]M$') as valid_minutes_only_no_space,
        COUNT(*) FILTER (WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text !~* '(AM|PM)') as no_ampm,
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}\\s*[AP]M$' AND "CreatedTime"::text !~ ':') as missing_colon,
        COUNT(*) FILTER (WHERE "CreatedTime" IS NULL) as null_times,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `,
    
    'ExpirationDate Analysis': `
      SELECT 
        COUNT(*) FILTER (WHERE "ExpirationDate"::text ~ '^\\d{4}-\\d{2}-\\d{2}$') as valid_iso_date,
        COUNT(*) FILTER (WHERE "ExpirationDate"::text ~ '^\\d{1,2}/\\d{1,2}/\\d{2,4}$') as slash_format,
        COUNT(*) FILTER (WHERE "ExpirationDate" IS NOT NULL AND "ExpirationDate"::text !~ '^\\d{4}-\\d{2}-\\d{2}$' AND "ExpirationDate"::text !~ '^\\d{1,2}/\\d{1,2}/\\d{2,4}$') as invalid_format,
        COUNT(*) FILTER (WHERE "ExpirationDate" IS NULL) as null_dates,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `
  };
  
  for (const [name, query] of Object.entries(queries)) {
    console.log(`\n${name}:`);
    console.log('─'.repeat(50));
    try {
      const results = await executeSQL(query);
      if (results.length > 0) {
        console.table(results[0]);
      }
    } catch (error) {
      console.error(`Error running ${name}:`, error.message);
    }
  }
}

/**
 * Run the fix script
 */
async function runFix() {
  console.log('\n🔧 Running date/time fixes...\n');
  
  const sqlFile = join(__dirname, '..', 'database', 'fix_all_dates_and_times.sql');
  const sql = fs.readFileSync(sqlFile, 'utf8');
  
  const pool = new Pool(dbConfig);
  
  try {
    // Extract and execute UPDATE statements only (skip SELECT/verification)
    const updateStatements = sql
      .split(/;[\r\n]+/)
      .map(s => s.trim())
      .filter(s => {
        const upper = s.toUpperCase().trim();
        return upper.startsWith('UPDATE') && !upper.includes('-- Skip');
      });
    
    console.log(`Found ${updateStatements.length} UPDATE statements to execute...\n`);
    
    for (let i = 0; i < updateStatements.length; i++) {
      const statement = updateStatements[i];
      
      try {
        const result = await pool.query(statement);
        console.log(`✅ Update ${i + 1}/${updateStatements.length}: ${result.rowCount || 0} rows affected`);
      } catch (error) {
        console.error(`❌ Error in update ${i + 1}:`, error.message);
        // Continue with next statement
      }
    }
    
    console.log('\n✅ All fix statements executed!\n');
  } finally {
    await pool.end();
  }
}

/**
 * Verify fixes
 */
async function verifyFixes() {
  console.log('\n✅ Verifying fixes...\n');
  
  const queries = {
    'CreatedDate Verification': `
      SELECT 
        COUNT(*) FILTER (WHERE "CreatedDate"::text ~ '^\\d{4}-\\d{2}-\\d{2}$') as valid_format,
        COUNT(*) FILTER (WHERE "CreatedDate" IS NOT NULL AND "CreatedDate"::text !~ '^\\d{4}-\\d{2}-\\d{2}$') as still_invalid,
        COUNT(*) FILTER (WHERE "CreatedDate" IS NULL) as null_count,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `,
    
    'CreatedTime Verification': `
      SELECT 
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}:\\d{2}\\s+[AP]M$') as valid_format,
        COUNT(*) FILTER (WHERE "CreatedTime"::text ~ '^\\d{1,2}:\\d{2}\\s+[AP]M$') as minutes_only_valid,
        COUNT(*) FILTER (WHERE "CreatedTime" IS NOT NULL AND "CreatedTime"::text !~ '^\\d{1,2}:\\d{2}(:\\d{2})?\\s+[AP]M$') as still_invalid,
        COUNT(*) FILTER (WHERE "CreatedTime" IS NULL) as null_count,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `,
    
    'ExpirationDate Verification': `
      SELECT 
        COUNT(*) FILTER (WHERE "ExpirationDate"::text ~ '^\\d{4}-\\d{2}-\\d{2}$') as valid_format,
        COUNT(*) FILTER (WHERE "ExpirationDate" IS NOT NULL AND "ExpirationDate"::text !~ '^\\d{4}-\\d{2}-\\d{2}$') as still_invalid,
        COUNT(*) FILTER (WHERE "ExpirationDate" IS NULL) as null_count,
        COUNT(*) as total_rows
      FROM "OptionsFlow_monthly"
    `
  };
  
  for (const [name, query] of Object.entries(queries)) {
    console.log(`\n${name}:`);
    console.log('─'.repeat(50));
    try {
      const results = await executeSQL(query);
      if (results.length > 0) {
        const row = results[0];
        console.table(row);
        
        // Show percentage
        if (row.total_rows > 0) {
          const validPct = ((row.valid_format || 0) / row.total_rows * 100).toFixed(2);
          const invalidPct = ((row.still_invalid || 0) / row.total_rows * 100).toFixed(2);
          console.log(`   Valid: ${validPct}% | Invalid: ${invalidPct}%`);
        }
      }
    } catch (error) {
      console.error(`Error running ${name}:`, error.message);
    }
  }
}

/**
 * Main function
 */
async function main() {
  const args = process.argv.slice(2);
  const command = args[0] || 'all';
  
  console.log('🗄️  Database Date/Time Fix Script\n');
  console.log(`Connecting to: ${dbConfig.host}:${dbConfig.port}/${dbConfig.database}\n`);
  
  try {
    if (command === 'analyze' || command === 'all') {
      await analyzeDatabase();
    }
    
    if (command === 'fix' || command === 'all') {
      if (command === 'all') {
        console.log('\n' + '='.repeat(60));
        console.log('Press Enter to continue with fixes, or Ctrl+C to cancel...');
        // Note: In a real implementation, you might want to add a prompt here
      }
      await runFix();
    }
    
    if (command === 'verify' || command === 'all') {
      await verifyFixes();
    }
    
    console.log('\n✨ Done!\n');
    
  } catch (error) {
    console.error('\n❌ Error:', error.message);
    process.exit(1);
  }
}

// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
  main();
}

export { analyzeDatabase, runFix, verifyFixes };

