/**
 * Database Schema Validation Script
 * Validates that all required tables, indexes, and constraints exist
 */

import { rawQuery } from '../src/db.js';

const REQUIRED_TABLES = [
  'options_flow',
  'daily_analysis',
  'OptionsFlow_monthly',
  'AlertStream_monthly',
  'alertstream_monthly',
  'prices_intraday_1m',
  'prices_daily',
  'price_daily',
  'price_1m',
  'minute_bars_et',
  'daily_bars',
  'bucket_members'
];

async function validateSchema() {
  console.log('🔍 Starting database schema validation...\n');

  const issues = [];
  const warnings = [];

  try {
    // 1. Check all required tables exist
    console.log('📋 Checking required tables...');
    const tablesQuery = `
      SELECT table_name 
      FROM information_schema.tables 
      WHERE table_schema = 'public' 
        AND table_name = ANY($1::text[])
      ORDER BY table_name;
    `;
    const existingTables = await rawQuery(tablesQuery, [REQUIRED_TABLES]);
    const existingTableNames = existingTables.map(t => t.table_name);

    for (const table of REQUIRED_TABLES) {
      if (existingTableNames.includes(table)) {
        console.log(`  ✅ ${table}`);
      } else {
        console.log(`  ❌ ${table} - MISSING`);
        issues.push(`Missing table: ${table}`);
      }
    }

    // 2. Check indexes on critical tables
    console.log('\n📊 Checking indexes on critical tables...');
    const indexesQuery = `
      SELECT tablename, indexname, indexdef
      FROM pg_indexes
      WHERE schemaname = 'public'
        AND tablename IN ('prices_intraday_1m', 'prices_daily', 'OptionsFlow_monthly')
      ORDER BY tablename, indexname;
    `;
    const indexes = await rawQuery(indexesQuery);
    
    const criticalIndexes = {
      'prices_intraday_1m': ['idx_prices_intraday_1m_symbol_ts', 'idx_prices_intraday_1m_ts'],
      'prices_daily': ['idx_prices_daily_symbol_date', 'idx_prices_daily_date'],
      'OptionsFlow_monthly': ['idx_optionsflow_monthly_symbol', 'idx_optionsflow_monthly_timestamp']
    };

    for (const [table, requiredIndexes] of Object.entries(criticalIndexes)) {
      const tableIndexes = indexes.filter(idx => idx.tablename === table);
      const existingIndexNames = tableIndexes.map(idx => idx.indexname);
      
      for (const indexName of requiredIndexes) {
        if (existingIndexNames.some(name => name.includes(indexName.split('_').slice(-2).join('_')))) {
          console.log(`  ✅ ${table}.${indexName}`);
        } else {
          console.log(`  ⚠️  ${table}.${indexName} - Missing or different name`);
          warnings.push(`Index ${indexName} on ${table} may be missing`);
        }
      }
    }

    // 3. Verify PRIMARY KEY constraints
    console.log('\n🔑 Checking PRIMARY KEY constraints...');
    const pkQuery = `
      SELECT tc.table_name, kc.column_name, tc.constraint_name
      FROM information_schema.table_constraints tc
      JOIN information_schema.key_column_usage kc
        ON tc.constraint_name = kc.constraint_name
      WHERE tc.constraint_type = 'PRIMARY KEY'
        AND tc.table_schema = 'public'
        AND tc.table_name IN ('prices_intraday_1m', 'prices_daily')
      ORDER BY tc.table_name;
    `;
    const primaryKeys = await rawQuery(pkQuery);

    const expectedPKs = {
      'prices_intraday_1m': ['symbol', 'ts'],
      'prices_daily': ['symbol', 'Date']
    };

    for (const [table, expectedCols] of Object.entries(expectedPKs)) {
      const tablePKs = primaryKeys.filter(pk => pk.table_name === table);
      const pkColumns = tablePKs.map(pk => pk.column_name);
      
      const hasAllColumns = expectedCols.every(col => 
        pkColumns.some(pkCol => pkCol.toLowerCase() === col.toLowerCase())
      );
      
      if (hasAllColumns && tablePKs.length > 0) {
        console.log(`  ✅ ${table} - PRIMARY KEY on (${expectedCols.join(', ')})`);
      } else {
        console.log(`  ❌ ${table} - Missing PRIMARY KEY on (${expectedCols.join(', ')})`);
        issues.push(`Missing PRIMARY KEY on ${table}`);
      }
    }

    // 4. Check for data type inconsistencies
    console.log('\n🔤 Checking data type consistency...');
    const dataTypeQuery = `
      SELECT 
        table_name,
        column_name,
        data_type,
        character_maximum_length
      FROM information_schema.columns
      WHERE table_schema = 'public'
        AND table_name IN ('prices_intraday_1m', 'prices_daily')
        AND column_name IN ('symbol', 'ts', 'Date', 'timestamp')
      ORDER BY table_name, column_name;
    `;
    const columns = await rawQuery(dataTypeQuery);

    // Check for redundant timestamp columns
    const intradayColumns = columns.filter(c => c.table_name === 'prices_intraday_1m');
    const hasTs = intradayColumns.some(c => c.column_name === 'ts');
    const hasTimestamp = intradayColumns.some(c => c.column_name === 'timestamp');
    
    if (hasTs && hasTimestamp) {
      console.log(`  ⚠️  prices_intraday_1m has both 'ts' and 'timestamp' columns (may be redundant)`);
      warnings.push('prices_intraday_1m has redundant timestamp columns');
    } else if (hasTs) {
      console.log(`  ✅ prices_intraday_1m uses 'ts' column`);
    } else if (hasTimestamp) {
      console.log(`  ⚠️  prices_intraday_1m only has 'timestamp' column (expected 'ts')`);
      warnings.push('prices_intraday_1m missing expected ts column');
    }

    // Check Date column capitalization
    const dailyColumns = columns.filter(c => c.table_name === 'prices_daily');
    const hasDate = dailyColumns.some(c => c.column_name === 'Date');
    if (hasDate) {
      console.log(`  ✅ prices_daily uses 'Date' column (capital D)`);
    } else {
      console.log(`  ⚠️  prices_daily may not have 'Date' column with capital D`);
      warnings.push('prices_daily Date column capitalization check');
    }

    // 5. Summary
    console.log('\n' + '='.repeat(60));
    console.log('📊 VALIDATION SUMMARY');
    console.log('='.repeat(60));
    
    if (issues.length === 0 && warnings.length === 0) {
      console.log('✅ Schema validation passed! All checks successful.');
      return true;
    }

    if (warnings.length > 0) {
      console.log(`\n⚠️  Warnings (${warnings.length}):`);
      warnings.forEach(w => console.log(`   - ${w}`));
    }

    if (issues.length > 0) {
      console.log(`\n❌ Issues found (${issues.length}):`);
      issues.forEach(i => console.log(`   - ${i}`));
      console.log('\n💡 Run the schema.sql and missing_tables.sql scripts to fix issues.');
      return false;
    }

    console.log('\n✅ Schema validation passed with warnings.');
    return true;

  } catch (error) {
    console.error('\n❌ Schema validation failed with error:');
    console.error(error);
    return false;
  }
}

// Run validation
validateSchema()
  .then(success => {
    process.exit(success ? 0 : 1);
  })
  .catch(error => {
    console.error('Fatal error:', error);
    process.exit(1);
  });

