/**
 * Sync Today's NBA Games with Odds from SportsGameOdds
 * Fetches only today's games and updates odds in the database
 */
import { PrismaClient } from '../prisma_sports/generated/sports-client';
import SportsGameOdds from 'sports-odds-api';

const API_KEY = process.env.SPORTSGAMEODDS_API_KEY || '';

// Team name normalization
const TEAM_ABBR: Record<string, string> = {
  'Atlanta Hawks': 'ATL', 'Boston Celtics': 'BOS', 'Brooklyn Nets': 'BKN',
  'Charlotte Hornets': 'CHA', 'Chicago Bulls': 'CHI', 'Cleveland Cavaliers': 'CLE',
  'Dallas Mavericks': 'DAL', 'Denver Nuggets': 'DEN', 'Detroit Pistons': 'DET',
  'Golden State Warriors': 'GSW', 'Houston Rockets': 'HOU', 'Indiana Pacers': 'IND',
  'Los Angeles Clippers': 'LAC', 'Los Angeles Lakers': 'LAL', 'Memphis Grizzlies': 'MEM',
  'Miami Heat': 'MIA', 'Milwaukee Bucks': 'MIL', 'Minnesota Timberwolves': 'MIN',
  'New Orleans Pelicans': 'NOP', 'New York Knicks': 'NYK', 'Oklahoma City Thunder': 'OKC',
  'Orlando Magic': 'ORL', 'Philadelphia 76ers': 'PHI', 'Phoenix Suns': 'PHX',
  'Portland Trail Blazers': 'POR', 'Sacramento Kings': 'SAC', 'San Antonio Spurs': 'SAS',
  'Toronto Raptors': 'TOR', 'Utah Jazz': 'UTA', 'Washington Wizards': 'WAS',
  // Abbreviations map to themselves
  'ATL': 'ATL', 'BOS': 'BOS', 'BKN': 'BKN', 'CHA': 'CHA', 'CHI': 'CHI', 'CLE': 'CLE',
  'DAL': 'DAL', 'DEN': 'DEN', 'DET': 'DET', 'GSW': 'GSW', 'HOU': 'HOU', 'IND': 'IND',
  'LAC': 'LAC', 'LAL': 'LAL', 'MEM': 'MEM', 'MIA': 'MIA', 'MIL': 'MIL', 'MIN': 'MIN',
  'NOP': 'NOP', 'NYK': 'NYK', 'OKC': 'OKC', 'ORL': 'ORL', 'PHI': 'PHI', 'PHX': 'PHX',
  'POR': 'POR', 'SAC': 'SAC', 'SAS': 'SAS', 'TOR': 'TOR', 'UTA': 'UTA', 'WAS': 'WAS',
};

function normalizeTeam(name: string): string {
  return TEAM_ABBR[name] || name.toUpperCase().replace(/\s+/g, '').substring(0, 3);
}

async function main() {
  if (!API_KEY) {
    console.error('SPORTSGAMEODDS_API_KEY not set');
    process.exit(1);
  }

  const prisma = new PrismaClient();
  const client = new SportsGameOdds({
    apiKeyHeader: API_KEY,
    apiKeyParam: API_KEY,
    maxRetries: 3,
    timeout: 30000,
  });

  try {
    // Get today in EST (for American sports)
    const now = new Date();
    const estOffset = -5 * 60; // EST is UTC-5
    const estTime = new Date(now.getTime() + (estOffset + now.getTimezoneOffset()) * 60 * 1000);
    const todayEST = estTime.toISOString().slice(0, 10);

    // Tomorrow EST for the date range
    const tomorrowEST = new Date(estTime);
    tomorrowEST.setDate(tomorrowEST.getDate() + 1);
    const tomorrowIso = tomorrowEST.toISOString().slice(0, 10);

    console.log(`Fetching NBA games for ${todayEST} (EST)...`);

    const events: any[] = [];
    for await (const event of client.events.get({
      leagueID: 'NBA',
      sportID: 'BASKETBALL',
      startDate: todayEST,
      endDate: tomorrowIso,
      oddsAvailable: true,
      limit: 50,
    })) {
      events.push(event);
      if (events.length >= 50) break;
    }

    console.log(`Found ${events.length} NBA events with odds`);

    let updated = 0;
    let created = 0;

    for (const event of events) {
      const eventID = event.eventID;
      const gameDate = event.status?.startsAt ? new Date(event.status.startsAt) : null;
      if (!gameDate) continue;

      const homeTeamRaw = event.teams?.home?.names?.short || event.teams?.home?.names?.medium || '';
      const awayTeamRaw = event.teams?.away?.names?.short || event.teams?.away?.names?.medium || '';
      const homeTeam = normalizeTeam(homeTeamRaw);
      const awayTeam = normalizeTeam(awayTeamRaw);

      // Extract odds from the event
      const odds = event.odds || {};
      let moneylineHome: number | null = null;
      let moneylineAway: number | null = null;
      let spreadHome: number | null = null;
      let spreadAway: number | null = null;
      let total: number | null = null;

      for (const [key, market] of Object.entries(odds)) {
        if (!market || typeof market !== 'object') continue;
        const m = market as any;
        const k = key.toLowerCase();

        // Moneyline
        if (k.includes('-ml-home') && (m.bookOdds || m.fairOdds)) {
          moneylineHome = Math.round(Number(m.bookOdds || m.fairOdds));
        }
        if (k.includes('-ml-away') && (m.bookOdds || m.fairOdds)) {
          moneylineAway = Math.round(Number(m.bookOdds || m.fairOdds));
        }

        // Spread
        if (k.includes('-sp-home') && m.bookSpread != null) {
          spreadHome = Number(m.bookSpread);
        }
        if (k.includes('-sp-away') && m.bookSpread != null) {
          spreadAway = Number(m.bookSpread);
        }

        // Total (over/under) - check multiple possible field names
        if (k.includes('-ou-') && !total) {
          // Try various field names for total line
          const totalValue = m.bookOverUnder ?? m.overUnder ?? m.line ?? m.bookLine ?? m.fairOverUnder;
          if (totalValue != null && Number(totalValue) > 100) { // NBA totals are typically 200+
            total = Number(totalValue);
          }
        }
        // Also check game total market
        if (k.includes('game-ou') && m.overUnder != null) {
          total = Number(m.overUnder);
        }
      }

      const hasOdds = moneylineHome != null || spreadHome != null || total != null;
      if (!hasOdds) continue;

      console.log(`  ${awayTeam} @ ${homeTeam}: ML ${moneylineHome}/${moneylineAway}, Spread ${spreadHome}, Total ${total}`);

      // Calculate season
      const gameYear = gameDate.getFullYear();
      const gameMonth = gameDate.getMonth();
      const season = gameMonth >= 9 ? gameYear : gameYear - 1;

      // Find existing game or create new one
      const externalGameId = `sgo:${eventID}`;

      try {
        // Try to find by external ID first
        let game = await prisma.sportsGame.findFirst({
          where: {
            league: 'nba',
            externalGameId,
          },
        });

        if (!game) {
          // Try to find by matchup and date
          const dayStart = new Date(gameDate);
          dayStart.setHours(0, 0, 0, 0);
          const dayEnd = new Date(gameDate);
          dayEnd.setHours(23, 59, 59, 999);

          game = await prisma.sportsGame.findFirst({
            where: {
              league: 'nba',
              homeTeam,
              awayTeam,
              gameDate: { gte: dayStart, lte: dayEnd },
            },
          });
        }

        if (game) {
          // Update existing game with odds
          await prisma.sportsGame.update({
            where: { id: game.id },
            data: {
              moneylineHome,
              moneylineAway,
              spreadHome,
              spreadAway,
              total,
              oddsUpdatedAt: new Date(),
              updatedAt: new Date(),
            },
          });
          updated++;
        } else {
          // Create new game
          await prisma.sportsGame.create({
            data: {
              league: 'nba',
              externalGameId,
              homeTeam,
              awayTeam,
              gameDate,
              season,
              moneylineHome,
              moneylineAway,
              spreadHome,
              spreadAway,
              total,
              status: event.status?.displayShort || 'scheduled',
              oddsUpdatedAt: new Date(),
              updatedAt: new Date(),
            },
          });
          created++;
        }
      } catch (err) {
        console.error(`  Error processing ${awayTeam} @ ${homeTeam}:`, err);
      }
    }

    console.log(`\n=== COMPLETE ===`);
    console.log(`Updated: ${updated} games`);
    console.log(`Created: ${created} games`);

  } finally {
    await prisma.$disconnect();
  }
}

main().catch(console.error);
