/**
 * Data Integrity & Accuracy Stress Test
 * Tests exact data retrieval, database consistency, and data gap handling
 */

import { getSportsDb } from '../src/lib/sportsDb';
import * as directQuery from '../src/lib/directSportsQuery';

interface TestResult {
  query: string;
  category: string;
  status: 'PASS' | 'PARTIAL' | 'FAIL' | 'NO_DATA';
  expected?: string;
  actual?: string;
  details?: string;
  confidence?: number;
  dataSource?: string;
}

const results: TestResult[] = [];

async function runTest(
  query: string,
  category: string,
  testFn: () => Promise<{ found: boolean; data?: any; details?: string }>
): Promise<void> {
  try {
    const result = await testFn();
    results.push({
      query,
      category,
      status: result.found ? 'PASS' : 'NO_DATA',
      actual: result.data ? JSON.stringify(result.data).slice(0, 200) : undefined,
      details: result.details,
      dataSource: 'sportsdb'
    });
  } catch (error: any) {
    results.push({
      query,
      category,
      status: 'FAIL',
      details: error.message
    });
  }
}

async function main() {
  console.log('='.repeat(60));
  console.log('DATA INTEGRITY & ACCURACY STRESS TEST');
  console.log('='.repeat(60));
  console.log();

  const db = getSportsDb();

  // ============================================================
  // CATEGORY 1: Verifiable Historical Facts
  // ============================================================
  console.log('📊 CATEGORY 1: Verifiable Historical Facts\n');

  // Test 1: Super Bowl LVIII
  await runTest(
    'Super Bowl LVIII final score (Chiefs vs 49ers)',
    'Historical Facts',
    async () => {
      const game = await db.sportsGame.findFirst({
        where: {
          league: 'nfl',
          OR: [
            { homeTeam: { contains: 'KC', mode: 'insensitive' } },
            { homeTeam: { contains: 'Chiefs', mode: 'insensitive' } }
          ],
          gameDate: { gte: new Date('2024-02-01'), lte: new Date('2024-02-15') },
          awayTeam: { contains: 'SF', mode: 'insensitive' }
        }
      });
      return {
        found: !!game,
        data: game ? { home: game.homeTeam, away: game.awayTeam, homeScore: game.homeScore, awayScore: game.awayScore } : null,
        details: game ? `Found: ${game.awayTeam} ${game.awayScore} - ${game.homeTeam} ${game.homeScore}` : 'Super Bowl not found'
      };
    }
  );

  // Test 2: 2023 NBA Finals Game 5 - Jokic stats
  await runTest(
    'Nikola Jokic stats in 2023 NBA Finals Game 5',
    'Historical Facts',
    async () => {
      const stats = await db.playerGameMetric.findMany({
        where: {
          playerName: { contains: 'Jokic', mode: 'insensitive' },
          gameDate: { gte: new Date('2023-06-12'), lte: new Date('2023-06-13') },
          league: 'nba'
        },
        take: 20
      });
      const grouped: Record<string, number> = {};
      stats.forEach(s => { grouped[s.statKey] = s.value; });
      return {
        found: stats.length > 0,
        data: grouped,
        details: `Found ${stats.length} stat entries for Jokic`
      };
    }
  );

  // Test 3: LeBron 40,000th point
  await runTest(
    'LeBron James 40,000th point game',
    'Historical Facts',
    async () => {
      const game = await db.playerGameMetric.findFirst({
        where: {
          playerName: { contains: 'LeBron', mode: 'insensitive' },
          gameDate: { gte: new Date('2024-03-01'), lte: new Date('2024-03-05') },
          statKey: { in: ['points', 'espn_pts', 'PTS'] }
        },
        orderBy: { gameDate: 'desc' }
      });
      return {
        found: !!game,
        data: game ? { date: game.gameDate, points: game.value, team: game.team } : null,
        details: game ? `Found: ${game.gameDate?.toISOString().slice(0,10)} - ${game.value} pts` : 'Game not found'
      };
    }
  );

  // Test 4: Shohei Ohtani 2023 HR total
  await runTest(
    'Shohei Ohtani 2023 MLB home run total',
    'Historical Facts',
    async () => {
      const hrs = await db.playerGameMetric.findMany({
        where: {
          playerName: { contains: 'Ohtani', mode: 'insensitive' },
          league: 'mlb',
          season: 2023,
          statKey: { in: ['home_runs', 'HR', 'homeRuns'] }
        }
      });
      const total = hrs.reduce((sum, h) => sum + h.value, 0);
      return {
        found: hrs.length > 0,
        data: { gamesWithHR: hrs.length, totalHR: total },
        details: `Found ${hrs.length} games with HR data, total: ${total}`
      };
    }
  );

  // Test 5: Connor McDavid 2023 Stanley Cup Finals Game 4
  await runTest(
    'Connor McDavid 2023 Stanley Cup Finals Game 4 stats',
    'Historical Facts',
    async () => {
      const stats = await db.playerGameMetric.findMany({
        where: {
          playerName: { contains: 'McDavid', mode: 'insensitive' },
          league: 'nhl',
          gameDate: { gte: new Date('2023-06-01'), lte: new Date('2023-06-15') }
        },
        take: 20
      });
      return {
        found: stats.length > 0,
        data: stats.slice(0, 5).map(s => ({ stat: s.statKey, value: s.value })),
        details: `Found ${stats.length} stat entries for McDavid in Finals`
      };
    }
  );

  // ============================================================
  // CATEGORY 2: Database Consistency Checks
  // ============================================================
  console.log('\n🔗 CATEGORY 2: Database Consistency Checks\n');

  // Test 6: Cross-reference - LeBron stats when AD scored 40+
  await runTest(
    'LeBron stats when AD scored 40+ points',
    'Cross-Reference',
    async () => {
      // Find games where AD scored 40+
      const adGames = await db.playerGameMetric.findMany({
        where: {
          playerName: { contains: 'Davis', mode: 'insensitive' },
          statKey: { in: ['points', 'espn_pts', 'PTS'] },
          value: { gte: 40 },
          league: 'nba'
        },
        select: { gameDate: true, value: true }
      });

      if (adGames.length === 0) {
        return { found: false, details: 'No AD 40+ point games found' };
      }

      // Get LeBron's stats on those dates
      const dates = adGames.map(g => g.gameDate?.toISOString().slice(0, 10)).filter(Boolean);
      const lebronStats = await db.playerGameMetric.findMany({
        where: {
          playerName: { contains: 'LeBron', mode: 'insensitive' },
          statKey: { in: ['points', 'espn_pts', 'PTS'] },
          gameDate: { in: adGames.map(g => g.gameDate).filter(Boolean) as Date[] }
        }
      });

      return {
        found: lebronStats.length > 0,
        data: { adGames: adGames.length, lebronMatchedGames: lebronStats.length },
        details: `Found ${adGames.length} AD 40+ games, ${lebronStats.length} LeBron matches`
      };
    }
  );

  // Test 7: Games where team won but didn't cover spread
  await runTest(
    'Games where team won but failed to cover spread',
    'Cross-Reference',
    async () => {
      const games = await db.sportsGame.findMany({
        where: {
          homeScore: { not: null },
          awayScore: { not: null },
          spreadHome: { not: null },
          league: { in: ['nba', 'nfl'] }
        },
        take: 1000,
        orderBy: { gameDate: 'desc' }
      });

      let winButNotCover = 0;
      const examples: any[] = [];

      for (const g of games) {
        if (g.homeScore === null || g.awayScore === null || g.spreadHome === null) continue;

        const homeWon = g.homeScore > g.awayScore;
        const margin = g.homeScore - g.awayScore;
        const homeCovered = margin + g.spreadHome > 0;

        if (homeWon && !homeCovered && examples.length < 3) {
          examples.push({
            game: `${g.awayTeam}@${g.homeTeam}`,
            score: `${g.awayScore}-${g.homeScore}`,
            spread: g.spreadHome
          });
          winButNotCover++;
        } else if (homeWon && !homeCovered) {
          winButNotCover++;
        }
      }

      return {
        found: winButNotCover > 0,
        data: { count: winButNotCover, examples },
        details: `Found ${winButNotCover} games where home team won but didn't cover`
      };
    }
  );

  // Test 8: Longest winning streak 2023-24 NBA
  await runTest(
    'Longest NBA winning streak 2023-24 season',
    'Temporal Consistency',
    async () => {
      const games = await db.sportsGame.findMany({
        where: {
          league: 'nba',
          season: 2024,
          homeScore: { not: null }
        },
        orderBy: { gameDate: 'asc' }
      });

      // Track streaks per team
      const teamStreaks: Record<string, { current: number; max: number; dates: string[] }> = {};

      for (const g of games) {
        if (!g.homeScore || !g.awayScore) continue;

        const homeWon = g.homeScore > g.awayScore;
        const date = g.gameDate.toISOString().slice(0, 10);

        // Update home team
        if (!teamStreaks[g.homeTeam]) teamStreaks[g.homeTeam] = { current: 0, max: 0, dates: [] };
        if (homeWon) {
          teamStreaks[g.homeTeam].current++;
          teamStreaks[g.homeTeam].dates.push(date);
        } else {
          if (teamStreaks[g.homeTeam].current > teamStreaks[g.homeTeam].max) {
            teamStreaks[g.homeTeam].max = teamStreaks[g.homeTeam].current;
          }
          teamStreaks[g.homeTeam].current = 0;
          teamStreaks[g.homeTeam].dates = [];
        }

        // Update away team
        if (!teamStreaks[g.awayTeam]) teamStreaks[g.awayTeam] = { current: 0, max: 0, dates: [] };
        if (!homeWon) {
          teamStreaks[g.awayTeam].current++;
        } else {
          if (teamStreaks[g.awayTeam].current > teamStreaks[g.awayTeam].max) {
            teamStreaks[g.awayTeam].max = teamStreaks[g.awayTeam].current;
          }
          teamStreaks[g.awayTeam].current = 0;
        }
      }

      // Find longest streak
      let longestTeam = '';
      let longestStreak = 0;
      for (const [team, data] of Object.entries(teamStreaks)) {
        const maxStreak = Math.max(data.current, data.max);
        if (maxStreak > longestStreak) {
          longestStreak = maxStreak;
          longestTeam = team;
        }
      }

      return {
        found: longestStreak > 0,
        data: { team: longestTeam, streak: longestStreak },
        details: `Longest streak: ${longestTeam} with ${longestStreak} wins`
      };
    }
  );

  // ============================================================
  // CATEGORY 3: Known Data Gap Testing
  // ============================================================
  console.log('\n📉 CATEGORY 3: Known Data Gap Testing\n');

  // Test 9: Player props for opening night 2023
  await runTest(
    'Player props for Warriors vs Kings Oct 18, 2023',
    'Data Gap Testing',
    async () => {
      const props = await db.playerPropLine.findMany({
        where: {
          league: 'nba',
          gameDate: { gte: new Date('2023-10-18'), lte: new Date('2023-10-19') }
        },
        take: 10
      });

      return {
        found: props.length > 0,
        data: { propCount: props.length },
        details: props.length > 0
          ? `Found ${props.length} props for opening night`
          : 'NO DATA: Player props may not be available for early season games'
      };
    }
  );

  // Test 10: Advanced analytics for 1998 NBA Finals
  await runTest(
    'Advanced analytics (PER) for 1998 NBA Finals',
    'Data Gap Testing',
    async () => {
      const stats = await db.playerGameMetric.findMany({
        where: {
          league: 'nba',
          gameDate: { gte: new Date('1998-06-01'), lte: new Date('1998-06-15') },
          statKey: { in: ['PER', 'PIE', 'per', 'pie'] }
        },
        take: 10
      });

      return {
        found: stats.length > 0,
        data: { statCount: stats.length },
        details: stats.length > 0
          ? `Found ${stats.length} advanced stats`
          : 'EXPECTED GAP: Advanced analytics not tracked before ~2010'
      };
    }
  );

  // Test 11: COVID shutdown games March 11, 2020
  await runTest(
    'Stats for canceled March 11, 2020 NBA games',
    'Data Gap Testing',
    async () => {
      const games = await db.sportsGame.findMany({
        where: {
          league: 'nba',
          gameDate: { gte: new Date('2020-03-11'), lte: new Date('2020-03-12') }
        }
      });

      const stats = await db.playerGameMetric.findMany({
        where: {
          league: 'nba',
          gameDate: { gte: new Date('2020-03-11'), lte: new Date('2020-03-12') }
        },
        take: 10
      });

      return {
        found: false,
        data: { gamesScheduled: games.length, statsFound: stats.length },
        details: 'EXPECTED: No stats for COVID shutdown date - games were canceled'
      };
    }
  );

  // ============================================================
  // CATEGORY 4: Data Coverage Summary
  // ============================================================
  console.log('\n📈 CATEGORY 4: Data Coverage Summary\n');

  // Test 12: Overall data coverage by league
  await runTest(
    'Data coverage summary by league',
    'Coverage Analysis',
    async () => {
      const leagues = ['nba', 'nfl', 'mlb', 'nhl'];
      const coverage: Record<string, any> = {};

      for (const league of leagues) {
        const [games, props, metrics] = await Promise.all([
          db.sportsGame.count({ where: { league, season: { gte: 2023 } } }),
          db.playerPropLine.count({ where: { league } }),
          db.playerGameMetric.count({ where: { league, season: { gte: 2023 } } })
        ]);
        coverage[league] = { games, props, metrics };
      }

      return {
        found: true,
        data: coverage,
        details: Object.entries(coverage).map(([l, c]) =>
          `${l.toUpperCase()}: ${c.games} games, ${c.props} props, ${c.metrics} metrics`
        ).join(' | ')
      };
    }
  );

  // Test 13: Odds coverage
  await runTest(
    'Betting odds coverage',
    'Coverage Analysis',
    async () => {
      const [withOdds, total] = await Promise.all([
        db.sportsGame.count({
          where: {
            moneylineHome: { not: null },
            season: { gte: 2024 }
          }
        }),
        db.sportsGame.count({
          where: { season: { gte: 2024 } }
        })
      ]);

      const coverage = total > 0 ? ((withOdds / total) * 100).toFixed(1) : '0';

      return {
        found: true,
        data: { withOdds, total, coverage: `${coverage}%` },
        details: `Odds coverage: ${withOdds}/${total} games (${coverage}%)`
      };
    }
  );

  // Test 14: API sources status
  await runTest(
    'API sources availability',
    'Coverage Analysis',
    async () => {
      const apis = directQuery.getAvailableApis();
      const configured = apis.filter(a => a.status === 'configured' || a.status === 'available');

      return {
        found: true,
        data: { total: apis.length, configured: configured.length, sources: configured.map(a => a.name) },
        details: `${configured.length}/${apis.length} API sources active: ${configured.map(a => a.name).join(', ')}`
      };
    }
  );

  // ============================================================
  // PRINT RESULTS
  // ============================================================
  console.log('\n' + '='.repeat(60));
  console.log('TEST RESULTS SUMMARY');
  console.log('='.repeat(60) + '\n');

  const passed = results.filter(r => r.status === 'PASS').length;
  const partial = results.filter(r => r.status === 'PARTIAL').length;
  const noData = results.filter(r => r.status === 'NO_DATA').length;
  const failed = results.filter(r => r.status === 'FAIL').length;

  console.log(`✅ PASSED: ${passed}`);
  console.log(`🟡 PARTIAL: ${partial}`);
  console.log(`📭 NO DATA: ${noData}`);
  console.log(`❌ FAILED: ${failed}`);
  console.log(`📊 TOTAL: ${results.length}`);
  console.log();

  // Detailed results
  for (const r of results) {
    const emoji = r.status === 'PASS' ? '✅' : r.status === 'NO_DATA' ? '📭' : r.status === 'PARTIAL' ? '🟡' : '❌';
    console.log(`${emoji} [${r.category}] ${r.query}`);
    if (r.details) console.log(`   ${r.details}`);
    console.log();
  }

  // Calculate accuracy score
  const accuracyScore = ((passed + partial * 0.5) / results.length * 100).toFixed(1);
  console.log('='.repeat(60));
  console.log(`ACCURACY SCORE: ${accuracyScore}%`);
  console.log('='.repeat(60));

  process.exit(0);
}

main().catch(e => {
  console.error('Test failed:', e);
  process.exit(1);
});
