#!/usr/bin/env npx tsx
/**
 * Verify Roster Accuracy Script
 * Cross-checks our canonical player data against live ESPN rosters.
 */

import { PrismaClient } from '../prisma_sports/generated/sports-client';

const prisma = new PrismaClient();

const ESPN_BASE = 'https://site.api.espn.com/apis/site/v2/sports';

const LEAGUE_CONFIG: Record<string, { sport: string; espnLeague: string }> = {
  nba: { sport: 'basketball', espnLeague: 'nba' },
  nfl: { sport: 'football', espnLeague: 'nfl' },
  nhl: { sport: 'hockey', espnLeague: 'nhl' },
};

const ESPN_ABBR_MAP: Record<string, Record<string, string>> = {
  nba: { 'GS': 'GSW', 'NO': 'NOP', 'NY': 'NYK', 'SA': 'SAS', 'UTAH': 'UTA', 'WSH': 'WAS' },
  nfl: { 'WSH': 'WAS' },
  nhl: { 'NJ': 'NJD', 'WSH': 'WAS', 'UTAH': 'UTA' },
};

function mapEspnAbbr(league: string, espnAbbr: string): string {
  return ESPN_ABBR_MAP[league]?.[espnAbbr] || espnAbbr;
}

function normalizeForMatch(name: string): string {
  return name.toLowerCase()
    .normalize('NFD').replace(/[\u0300-\u036f]/g, '')
    .replace(/[.']/g, '')
    .replace(/\s+(jr|sr|iii|ii|iv|v)$/i, '')
    .replace(/\s+/g, ' ')
    .trim();
}

async function verifyTeamRoster(league: string, espnTeamId: string, expectedAbbr: string) {
  const config = LEAGUE_CONFIG[league];
  const url = `${ESPN_BASE}/${config.sport}/${config.espnLeague}/teams/${espnTeamId}/roster`;

  const res = await fetch(url);
  const data = await res.json();
  const rawAthletes = data?.athletes || [];

  // Handle both flat array (NBA) and grouped by position (NFL/NHL)
  const athletes: any[] = [];
  for (const item of rawAthletes) {
    if (item?.fullName || item?.displayName) {
      // Flat format (direct athlete)
      athletes.push(item);
    } else if (item?.items) {
      // Grouped format (position group with items)
      athletes.push(...item.items);
    }
  }

  let matches = 0;
  let mismatches = 0;
  let notFound = 0;
  const errors: string[] = [];

  for (const player of athletes) {
    const espnName = player.fullName || player.displayName;
    if (!espnName) continue;

    const normalized = normalizeForMatch(espnName);

    const ourPlayer = await prisma.canonicalPlayer.findUnique({
      where: { league_normalizedName: { league, normalizedName: normalized } },
      include: { team: { select: { abbr: true } } }
    });

    if (!ourPlayer) {
      notFound++;
    } else if (ourPlayer.team?.abbr === expectedAbbr) {
      matches++;
    } else {
      mismatches++;
      errors.push(`${espnName}: expected ${expectedAbbr}, got ${ourPlayer.team?.abbr || 'none'}`);
    }
  }

  return { matches, mismatches, notFound, errors, total: athletes.length };
}

async function main() {
  console.log('='.repeat(60));
  console.log('ROSTER ACCURACY VERIFICATION');
  console.log('='.repeat(60) + '\n');

  for (const league of ['nba', 'nfl', 'nhl']) {
    console.log(`\n=== ${league.toUpperCase()} ===\n`);

    const config = LEAGUE_CONFIG[league];
    const teamsRes = await fetch(`${ESPN_BASE}/${config.sport}/${config.espnLeague}/teams?limit=50`);
    const teamsData = await teamsRes.json();
    const espnTeams = teamsData?.sports?.[0]?.leagues?.[0]?.teams || [];

    let totalMatches = 0;
    let totalMismatches = 0;
    let totalNotFound = 0;
    let totalPlayers = 0;

    // Check 5 random teams per league
    const shuffled = espnTeams.sort(() => 0.5 - Math.random());
    const sampled = shuffled.slice(0, 5);

    for (const t of sampled) {
      const abbr = mapEspnAbbr(league, t.team.abbreviation);
      const result = await verifyTeamRoster(league, t.team.id, abbr);

      totalMatches += result.matches;
      totalMismatches += result.mismatches;
      totalNotFound += result.notFound;
      totalPlayers += result.total;

      const pct = result.total > 0 ? ((result.matches / result.total) * 100).toFixed(0) : '0';
      console.log(`  ${abbr}: ${result.matches}/${result.total} correct (${pct}%), ${result.notFound} not in DB`);

      if (result.errors.length > 0 && result.errors.length <= 3) {
        result.errors.forEach(e => console.log(`    - ${e}`));
      }

      await new Promise(r => setTimeout(r, 200));
    }

    const overallPct = totalPlayers > 0 ? ((totalMatches / totalPlayers) * 100).toFixed(1) : '0';
    console.log(`\n  ${league.toUpperCase()} Overall: ${totalMatches}/${totalPlayers} (${overallPct}%) correct`);
    console.log(`  Not in database: ${totalNotFound}`);
  }

  await prisma.$disconnect();
}

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