import { espnFetch } from './espn-roster';

const ESPN_MLB_SCOREBOARD = 'https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/scoreboard';

export interface EspnProbableStarter {
  teamShort: string;
  teamName: string;
  name: string;
  shortName: string | null;
  playerId: string | null;
  era: number | null;
  record: string | null;
}

export interface EspnMlbProbables {
  eventId: string;
  date: string;
  homeStarter: EspnProbableStarter | null;
  awayStarter: EspnProbableStarter | null;
}

const probablesCache = new Map<string, Promise<EspnMlbProbables | null>>();

function toDateToken(isoLike: string | Date | number | null | undefined): string | null {
  if (isoLike == null) {
    return null;
  }

  let value: string;
  if (typeof isoLike === 'string') {
    value = isoLike.trim();
    if (!value) {
      return null;
    }
  } else if (isoLike instanceof Date) {
    if (Number.isNaN(isoLike.getTime())) {
      return null;
    }
    value = isoLike.toISOString();
  } else if (typeof isoLike === 'number') {
    const dt = new Date(isoLike);
    if (Number.isNaN(dt.getTime())) {
      return null;
    }
    value = dt.toISOString();
  } else if (typeof (isoLike as any)?.toISOString === 'function') {
    const dtValue = (isoLike as any).toISOString();
    if (typeof dtValue !== 'string' || !dtValue.trim()) {
      return null;
    }
    value = dtValue;
  } else {
    return null;
  }

  const datePart = value.slice(0, 10);
  return datePart.replace(/-/g, '');
}

function shiftDateToken(dateToken: string, dayOffset: number): string {
  const year = Number(dateToken.slice(0, 4));
  const month = Number(dateToken.slice(4, 6));
  const day = Number(dateToken.slice(6, 8));
  const dt = new Date(Date.UTC(year, month - 1, day));
  dt.setUTCDate(dt.getUTCDate() + dayOffset);
  return dt.toISOString().slice(0, 10).replace(/-/g, '');
}

function normalizeShort(short: string | null | undefined): string {
  return (short || '').trim().toUpperCase();
}

function extractStarter(competitor: any): EspnProbableStarter | null {
  const probables = Array.isArray(competitor?.probables) ? competitor.probables : [];
  const starter = probables.find((entry: any) =>
    entry?.name === 'probableStartingPitcher' ||
    entry?.abbreviation === 'SP'
  );
  const athlete = starter?.athlete;
  if (!athlete?.fullName && !athlete?.displayName) {
    return null;
  }

  const eraStat = Array.isArray(starter?.statistics)
    ? starter.statistics.find((stat: any) => stat?.abbreviation === 'ERA')
    : null;

  return {
    teamShort: normalizeShort(competitor?.team?.abbreviation),
    teamName: competitor?.team?.displayName || competitor?.team?.name || '',
    name: athlete.fullName || athlete.displayName,
    shortName: athlete.shortName || null,
    playerId: athlete.id ? String(athlete.id) : null,
    era: eraStat?.displayValue != null ? Number(eraStat.displayValue) : null,
    record: starter?.record || null,
  };
}

async function fetchScoreboard(dateToken: string): Promise<any> {
  return espnFetch(`${ESPN_MLB_SCOREBOARD}?dates=${dateToken}&limit=200`);
}

function findMatch(data: any, homeShort: string, awayShort: string): EspnMlbProbables | null {
  for (const event of data?.events || []) {
    const comp = event?.competitions?.[0];
    if (!comp) continue;
    const competitors = Array.isArray(comp.competitors) ? comp.competitors : [];
    const home = competitors.find((team: any) => team?.homeAway === 'home');
    const away = competitors.find((team: any) => team?.homeAway === 'away');
    if (!home || !away) continue;

    const homeAbbr = normalizeShort(home?.team?.abbreviation);
    const awayAbbr = normalizeShort(away?.team?.abbreviation);
    if (homeAbbr !== homeShort || awayAbbr !== awayShort) continue;

    return {
      eventId: String(event.id || ''),
      date: String(comp.startDate || event.date || ''),
      homeStarter: extractStarter(home),
      awayStarter: extractStarter(away),
    };
  }
  return null;
}

export async function getMlbProbableStarters(params: {
  homeShort: string;
  awayShort: string;
  startsAt: string | Date;
}): Promise<EspnMlbProbables | null> {
  const homeShort = normalizeShort(params.homeShort);
  const awayShort = normalizeShort(params.awayShort);
  if (!homeShort || !awayShort || !params.startsAt) {
    return null;
  }

  const baseDate = toDateToken(params.startsAt);
  if (!baseDate) {
    return null;
  }
  const cacheKey = `${baseDate}:${homeShort}:${awayShort}`;
  if (!probablesCache.has(cacheKey)) {
    probablesCache.set(cacheKey, (async () => {
      for (const offset of [0, -1, 1]) {
        const dateToken = shiftDateToken(baseDate, offset);
        const data = await fetchScoreboard(dateToken);
        const match = findMatch(data, homeShort, awayShort);
        if (match) return match;
      }
      return null;
    })());
  }

  return probablesCache.get(cacheKey)!;
}

export const __espnMlbInternals = {
  toDateToken,
};
