/**
 * ESPN public scoreboard adapter.
 *
 * ESPN's `site.api.espn.com` scoreboard endpoints are unauthenticated and
 * stable. They cover every sport we care about. We use them for:
 *   - Game schedule + status (scheduled / in progress / final)
 *   - Game-level moneyline + spread + total (when ESPN has odds)
 *   - Live scores during in-progress games
 *
 * They do NOT carry player props — that's other adapters' job.
 */

const axios = require('axios');
const rateLimiter = require('../rateLimiter');
const breaker = require('../circuitBreaker');

const ENDPOINTS = Object.freeze({
  nba:    'https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard',
  wnba:   'https://site.api.espn.com/apis/site/v2/sports/basketball/wnba/scoreboard',
  mlb:    'https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/scoreboard',
  nfl:    'https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard',
  nhl:    'https://site.api.espn.com/apis/site/v2/sports/hockey/nhl/scoreboard',
  mma:    'https://site.api.espn.com/apis/site/v2/sports/mma/ufc/scoreboard',
  golf:   'https://site.api.espn.com/apis/site/v2/sports/golf/pga/scoreboard',
  boxing: 'https://site.api.espn.com/apis/site/v2/sports/boxing/scoreboard',
});

const HTTP_TIMEOUT_MS = 8_000;
const SOURCE = 'espn';

function normalizeGame(event, sport) {
  const competition = event.competitions?.[0];
  if (!competition) return null;
  const competitors = competition.competitors || [];
  const home = competitors.find((c) => c.homeAway === 'home');
  const away = competitors.find((c) => c.homeAway === 'away');
  const oddsRow = (competition.odds || [])[0];

  return {
    game_id: String(event.id),
    sport,
    away: away?.team?.abbreviation || null,
    home: home?.team?.abbreviation || null,
    away_name: away?.team?.displayName || null,
    home_name: home?.team?.displayName || null,
    start_time: event.date,
    status: event.status?.type?.name || null,    // STATUS_SCHEDULED | STATUS_IN_PROGRESS | STATUS_FINAL
    venue: competition.venue?.fullName || null,
    odds: oddsRow
      ? {
          provider: oddsRow.provider?.name || null,
          details: oddsRow.details || null,
          spread: oddsRow.spread ?? null,
          over_under: oddsRow.overUnder ?? null,
        }
      : null,
    score:
      event.status?.type?.state === 'in'
        ? {
            away: parseInt(away?.score ?? '0', 10),
            home: parseInt(home?.score ?? '0', 10),
            period: event.status?.period,
            clock: event.status?.displayClock,
          }
        : null,
    source: SOURCE,
    fetched_at: new Date().toISOString(),
  };
}

async function getGames(sport) {
  const url = ENDPOINTS[sport];
  if (!url) {
    const err = new Error(`espn adapter does not support sport: ${sport}`);
    err.skipBreaker = true;
    throw err;
  }
  await rateLimiter.take(SOURCE);
  return breaker.call(SOURCE, async () => {
    const res = await axios.get(url, {
      timeout: HTTP_TIMEOUT_MS,
      headers: { 'User-Agent': 'VYNDR/1.0 (+https://vyndr.app)' },
      validateStatus: (s) => s >= 200 && s < 500,
    });
    if (res.status >= 400) {
      const err = new Error(`espn returned ${res.status}`);
      err.upstream = SOURCE;
      throw err;
    }
    const events = Array.isArray(res.data?.events) ? res.data.events : [];
    return events.map((e) => normalizeGame(e, sport)).filter(Boolean);
  });
}

async function getPlayerProps(/* sport */) {
  // ESPN's public API doesn't carry player props.
  return [];
}

module.exports = { name: SOURCE, getGames, getPlayerProps, ENDPOINTS };
