'use strict';

/**
 * scripts/propline-audit.js (Session 56) — the data-source audit.
 *
 * Inventories what our providers CAN send (from code) and what the FREE
 * settled-result APIs (MLB Stats, ESPN) actually return, so we can map every
 * prop stat_type to its box-score field. PropLine live fetch runs only when
 * PROPLINE_API_KEY_* are present (they aren't in dev) — otherwise we report the
 * authoritative code inventory (MARKETS × MARKET_MAP).
 *
 * Usage: node scripts/propline-audit.js   (writes JSON to stdout)
 */

require('dotenv').config({ quiet: true });
const propline = require('../src/services/adapters/proplineAdapter');
const { MARKET_MAP } = require('../src/utils/oddsNormalizer');

const out = { generatedAt: new Date().toISOString(), sections: {} };

async function getJson(url, headers) {
  const r = await fetch(url, { headers: headers || {}, signal: AbortSignal.timeout(12000) });
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
  return r.json();
}

// 1. PropLine code inventory — the markets we REQUEST per sport + the stat_type
// each normalizes to (or "UNMAPPED" if MARKET_MAP has no entry → silent zero).
function proplineInventory() {
  const { MARKETS, SPORT_KEYS } = propline.__internals;
  const map = MARKET_MAP || {};
  const inv = {};
  for (const [sport, markets] of Object.entries(MARKETS)) {
    inv[sport] = {
      sportKey: SPORT_KEYS[sport],
      requested: markets.map((m) => ({ market: m, stat_type: map[m] || 'UNMAPPED' })),
    };
  }
  // Also list every MARKET_MAP entry (what we CAN normalize even if not requested).
  inv._allMappedMarkets = Object.entries(map).map(([m, s]) => ({ market: m, stat_type: s }));
  inv._hasKeys = propline.hasKeys();
  return inv;
}

// 2. The Odds API active sports (FREE — /v4/sports does not spend quota).
async function oddsApiSports() {
  const key = process.env.ODDS_API_KEY;
  if (!key) return { skipped: 'no ODDS_API_KEY' };
  try {
    const data = await getJson(`https://api.the-odds-api.com/v4/sports?apiKey=${key}`);
    return (data || [])
      .filter((s) => s.active)
      .map((s) => ({ key: s.key, group: s.group, title: s.title }));
  } catch (e) { return { error: e.message }; }
}

// 3. MLB Stats API — a recent FINAL game's boxscore field keys + a game-log row.
async function mlbBoxscore() {
  try {
    // Yesterday's schedule.
    const d = new Date(Date.now() - 24 * 3600 * 1000).toISOString().slice(0, 10);
    const sched = await getJson(`https://statsapi.mlb.com/api/v1/schedule?sportId=1&date=${d}`);
    const games = (sched.dates?.[0]?.games) || [];
    const final = games.find((g) => g.status?.abstractGameState === 'Final') || games[0];
    if (!final) return { note: `no games ${d}` };
    const box = await getJson(`https://statsapi.mlb.com/api/v1/game/${final.gamePk}/boxscore`);
    // Pull one batter + one pitcher stat object.
    const sampleTeam = box.teams?.away || box.teams?.home || {};
    const players = Object.values(sampleTeam.players || {});
    const batter = players.find((p) => p.stats?.batting && Object.keys(p.stats.batting).length);
    const pitcher = players.find((p) => p.stats?.pitching && Object.keys(p.stats.pitching).length);
    return {
      date: d, gamePk: final.gamePk, matchup: final.teams?.away?.team?.name + ' @ ' + final.teams?.home?.team?.name,
      battingFields: batter ? Object.keys(batter.stats.batting) : [],
      pitchingFields: pitcher ? Object.keys(pitcher.stats.pitching) : [],
      sampleBatting: batter ? batter.stats.batting : null,
      samplePitching: pitcher ? pitcher.stats.pitching : null,
    };
  } catch (e) { return { error: e.message }; }
}

// 4. ESPN WNBA — today's scoreboard status + a completed game's boxscore labels.
async function espnWnba() {
  try {
    const sb = await getJson('https://site.api.espn.com/apis/site/v2/sports/basketball/wnba/scoreboard');
    const events = (sb.events || []).map((e) => ({ name: e.name, status: e.status?.type?.description, date: e.date }));
    const final = (sb.events || []).find((e) => e.status?.type?.completed);
    let boxLabels = null;
    if (final) {
      const summary = await getJson(`https://site.api.espn.com/apis/site/v2/sports/basketball/wnba/summary?event=${final.id}`);
      const teamStats = summary.boxscore?.players?.[0]?.statistics?.[0];
      boxLabels = teamStats ? { labels: teamStats.labels, names: teamStats.names } : null;
    }
    return { count: events.length, events, completedBoxLabels: boxLabels };
  } catch (e) { return { error: e.message }; }
}

// 5. ESPN soccer — check a common league scoreboard for activity.
async function espnSoccer() {
  try {
    const sb = await getJson('https://site.api.espn.com/apis/site/v2/sports/soccer/usa.1/scoreboard');
    const events = (sb.events || []).map((e) => ({ name: e.name, status: e.status?.type?.description }));
    return { league: 'usa.1 (MLS)', count: events.length, events: events.slice(0, 6) };
  } catch (e) { return { error: e.message }; }
}

(async () => {
  out.sections.proplineInventory = proplineInventory();
  out.sections.oddsApiActiveSports = await oddsApiSports();
  out.sections.mlbBoxscore = await mlbBoxscore();
  out.sections.espnWnba = await espnWnba();
  out.sections.espnSoccer = await espnSoccer();
  process.stdout.write(JSON.stringify(out, null, 2) + '\n');
})();
