// ESPN core API prop bets: per-athlete goalscorer odds (DraftKings, provider
// 100) — First Goalscorer / Last Goalscorer / To Score 2+ Goals, plus anytime
// variants. Line history is unrecoverable, so capture beats everything; the
// athlete $refs resolve to names lazily through a long-TTL cache.
import { cachedFetch } from './fetcher';

const CORE = 'https://sports.core.api.espn.com/v2/sports/soccer/leagues/fifa.world';
const SOURCE = 'espn-odds';
const PROVIDER = 100; // DraftKings on the core API

export interface ScorerProp {
  market: string;
  athleteName: string;
  american: number | null;
}

interface PropPage {
  pageCount?: number;
  items?: {
    type?: { name?: string; text?: string };
    athlete?: { $ref?: string };
    current?: { odds?: { american?: string | number } | string; american?: string };
    open?: unknown;
  }[];
}

const WANTED = /goalscorer|to score/i;

function americanOf(item: PropPage['items'] extends (infer T)[] | undefined ? T : never): number | null {
  const cur = item.current as { american?: string | number; odds?: { american?: string | number } } | undefined;
  const raw = cur?.american ?? cur?.odds?.american;
  if (raw == null) return null;
  const n = Number(String(raw).replace('+', ''));
  return Number.isFinite(n) ? n : null;
}

/** Resolve an athlete $ref to a display name (cached ~30 days). */
async function athleteName(ref: string): Promise<string | null> {
  const m = /athletes\/(\d+)/.exec(ref);
  if (!m) return null;
  try {
    const a = await cachedFetch<{ displayName?: string; fullName?: string }>(
      SOURCE,
      `espn:athlete:${m[1]}`,
      ref.replace(/^http:/, 'https:'),
      { ttl: 30 * 24 * 60 * 60_000, minInterval: 1_200 },
    );
    return a.displayName ?? a.fullName ?? null;
  } catch {
    return null;
  }
}

/** All scorer props for an event. Name resolution is deadline-bounded per
 *  call: cold caches fill across successive sweeps (each athlete lookup is
 *  cached ~30 days), warm caches resolve everything instantly. */
export async function fetchScorerProps(eventId: string, budgetMs = 45_000): Promise<ScorerProp[]> {
  const out: ScorerProp[] = [];
  const deadline = Date.now() + budgetMs;
  for (let page = 1; page <= 10; page++) {
    const url = `${CORE}/events/${eventId}/competitions/${eventId}/odds/${PROVIDER}/propBets?limit=100&page=${page}`;
    const d = await cachedFetch<PropPage>(SOURCE, `espn:props:${eventId}:${page}`, url, {
      ttl: 60 * 60_000,
      minInterval: 1_500,
    });
    for (const item of d.items ?? []) {
      const market = item.type?.text ?? item.type?.name ?? '';
      if (!WANTED.test(market)) continue;
      const ref = item.athlete?.$ref;
      if (!ref || Date.now() > deadline) continue;
      const name = await athleteName(ref);
      if (!name) continue;
      out.push({ market, athleteName: name, american: americanOf(item) });
    }
    if ((d.pageCount ?? 1) <= page) break;
  }
  return out;
}
