/**
 * Batch Forecast Generator
 * Pulls all events from SGO API across all leagues and generates
 * Grok AI forecasts for each one. Rate-limited to avoid API throttling.
 *
 * Usage: npx tsx src/workers/batch-forecasts.ts [--league nba] [--concurrency 2] [--delay 3000]
 */

import 'dotenv/config';
import pool from '../db';
import { fetchAllLeagueEvents, fetchEvents, LEAGUE_MAP, SgoEvent } from '../services/sgo';
import { getCachedForecast } from '../models/forecast';
import { buildForecast } from '../services/forecast-builder';

const args = process.argv.slice(2);
const leagueFilter = getArg('--league');
const concurrency = parseInt(getArg('--concurrency') || '2', 10);
const delayMs = parseInt(getArg('--delay') || '3000', 10);
const skipCached = !args.includes('--force');

function getArg(flag: string): string | null {
  const idx = args.indexOf(flag);
  return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : null;
}

function sleep(ms: number) {
  return new Promise(r => setTimeout(r, ms));
}

interface Stats {
  total: number;
  generated: number;
  cached: number;
  failed: number;
  skipped: number;
}

async function processEvent(event: SgoEvent, league: string, stats: Stats): Promise<void> {
  const homeTeam = event.teams?.home?.names?.long || 'Unknown';
  const awayTeam = event.teams?.away?.names?.long || 'Unknown';
  const label = `${awayTeam} @ ${homeTeam} (${league.toUpperCase()})`;

  // Check if already cached
  if (skipCached) {
    const cached = await getCachedForecast(event.eventID);
    if (cached && cached.forecast_data?.summary) {
      stats.cached++;
      console.log(`  [CACHED] ${label}`);
      return;
    }
  }

  try {
    // Generate forecast via the full builder so cached confidence uses the composite score.
    console.log(`  [GENERATING] ${label}...`);
    const result = await buildForecast(event, league, { ignoreCache: true });
    const forecast = result.forecast;

    stats.generated++;
    const conf = Math.round(result.confidenceScore * 100);
    console.log(`  [OK] ${label} — ${forecast.winner_pick} (${conf}% conf)`);
  } catch (err: any) {
    stats.failed++;
    console.error(`  [FAIL] ${label}: ${err.message}`);
  }
}

async function main() {
  console.log('='.repeat(60));
  console.log('RAINMAKER BATCH FORECAST GENERATOR');
  console.log('='.repeat(60));
  console.log(`Concurrency: ${concurrency} | Delay: ${delayMs}ms | Skip cached: ${skipCached}`);
  if (leagueFilter) console.log(`League filter: ${leagueFilter.toUpperCase()}`);
  console.log('');

  // Fetch all events
  let eventsByLeague: Record<string, SgoEvent[]>;

  if (leagueFilter && LEAGUE_MAP[leagueFilter]) {
    console.log(`Fetching ${leagueFilter.toUpperCase()} events...`);
    const events = await fetchEvents(leagueFilter);
    eventsByLeague = events.length > 0 ? { [leagueFilter]: events } : {};
  } else {
    console.log('Fetching events across all leagues...');
    eventsByLeague = await fetchAllLeagueEvents();
  }

  // Filter valid events
  const allEvents: Array<{ event: SgoEvent; league: string }> = [];
  for (const [lg, events] of Object.entries(eventsByLeague)) {
    const valid = events.filter(e => e.teams?.home?.names && e.teams?.away?.names);
    console.log(`  ${lg.toUpperCase()}: ${valid.length} valid events`);
    for (const event of valid) {
      allEvents.push({ event, league: lg });
    }
  }

  console.log(`\nTotal events to process: ${allEvents.length}`);
  console.log('-'.repeat(60));

  const stats: Stats = { total: allEvents.length, generated: 0, cached: 0, failed: 0, skipped: 0 };
  const startTime = Date.now();

  // Process in batches with concurrency limit
  for (let i = 0; i < allEvents.length; i += concurrency) {
    const batch = allEvents.slice(i, i + concurrency);
    const progress = `[${i + 1}-${Math.min(i + concurrency, allEvents.length)}/${allEvents.length}]`;
    console.log(`\n${progress} Processing batch...`);

    await Promise.all(batch.map(({ event, league }) => processEvent(event, league, stats)));

    // Rate limit delay between batches (skip on last batch)
    if (i + concurrency < allEvents.length) {
      await sleep(delayMs);
    }
  }

  const elapsed = Math.round((Date.now() - startTime) / 1000);

  console.log('\n' + '='.repeat(60));
  console.log('BATCH COMPLETE');
  console.log('='.repeat(60));
  console.log(`Total:     ${stats.total}`);
  console.log(`Generated: ${stats.generated}`);
  console.log(`Cached:    ${stats.cached} (already existed)`);
  console.log(`Failed:    ${stats.failed}`);
  console.log(`Time:      ${elapsed}s`);
  console.log('='.repeat(60));

  await pool.end();
  process.exit(stats.failed > 0 ? 1 : 0);
}

main().catch((err) => {
  console.error('Fatal error:', err);
  process.exit(1);
});
