'use strict';

/**
 * Per-sport snapshot cadence (Job 1) — the config that replaces baseball's
 * one-size-fits-all rhythm.
 *
 * WHY THIS EXISTS
 * The snapshot cron fired every ACTIVE sport at all five MLB slots
 * (14/19/22/1/3 UTC). But sports post their lines on entirely different
 * clocks, so that inheritance was wasteful in two directions:
 *   - WNBA props aren't posted at 14:00 UTC (10am ET) → that slot always
 *     graded 0 for WNBA (the "wnba:0" the audit flagged). Wasted work.
 *   - Soccer odds come from the odds-api key (500/MONTH, scarce). Running it
 *     at five slots/day is a third of the monthly budget for 1–2 matches.
 *
 * THE RULE: high frequency only when a sport's lines actually post/move,
 * near-zero otherwise. This is a SCHEDULING fix, not a volume one — "never a
 * gap" must never become "pull constantly", because burning the odds-api
 * quota by noon means nothing all afternoon (strictly worse than a gap).
 *
 * QUOTA HEADROOM (mapped from reality, 2026-07):
 *   - PropLine (mlb/nba/wnba props): 3 keys × 3,000/day = 9,000/day. Abundant.
 *     Five slots × a few sports × intraday is a rounding error against that.
 *   - The Odds API (soccer props + futures): 500/MONTH. Every soccer slot is
 *     ~1 credit. So soccer gets the fewest, best-timed slots and NO intraday
 *     refresh (a 20-min soccer refresh would burn ~36 credits/day = the whole
 *     month in ~2 weeks).
 *
 * DESIGN CONSTRAINT (low blast radius): every sport's hours are a SUBSET of the
 * scheduler's firing grid (snapshotScheduler.HOURS_UTC, default 14/19/22/1/3).
 * The scheduler still fires at those hours; this config just decides WHICH
 * sports run at each one. Keeping the union inside the grid means the
 * missed-cron watchdog (which references MLB) needs no change. If a sport ever
 * genuinely needs an hour outside the grid, add it to HOURS_UTC too AND scope
 * the overdue watchdog to MLB's hours (see snapshotScheduler).
 *
 * POSTING RHYTHMS (why each sport gets the hours it does):
 *   - mlb   — games + props all day; the full grid is correct. Keep 14/19/22/1/3.
 *   - nba   — off-season now (self-skips empty on PropLine, ~0 cost); in-season
 *             posts morning→afternoon ET. The full grid fits both. Keep.
 *   - wnba  — PropLine-backed (cheap), and games span EARLY AFTERNOON (weekend/
 *             holiday 1–3pm ET) through LATE-EVENING west-coast (10pm ET). A
 *             1pm ET game's props post ~morning ET, so the 14 UTC (10am ET) slot
 *             is the ONLY one early enough to catch them; 3 UTC (11pm ET) is the
 *             west-coast lock. Observed 2026-07-15: two afternoon WNBA games had
 *             already finished by the 22 UTC slot. So WNBA keeps the FULL grid —
 *             the earlier "drop 14/3 as waste" was wrong: on PropLine it costs a
 *             rounding error and the coverage is real. (An empty slot is an
 *             honest 'skipped', never a paged failure.)
 *   - soccer— World Cup live now (final Jul 19), club leagues resume Aug. Lines
 *             post well ahead and barely move; two well-placed odds-api reads
 *             (14 UTC morning research, 19 UTC pre-afternoon-match lock) cover a
 *             match day for ~2 credits. NO intraday (protects the 500/mo key).
 *
 * config-over-constants: to retune a sport, edit ONLY this table.
 */

const SPORT_CADENCE = Object.freeze({
  mlb:    { hours: [14, 19, 22, 1, 3], intraday: true,  source: 'propline' },
  nba:    { hours: [14, 19, 22, 1, 3], intraday: true,  source: 'propline' },
  wnba:   { hours: [14, 19, 22, 1, 3], intraday: true,  source: 'propline' },
  soccer: { hours: [14, 19],           intraday: false, source: 'odds-api' },
});

const ALL_SPORTS = Object.freeze(Object.keys(SPORT_CADENCE));

// The union of every sport's snapshot hours — the set the scheduler must fire
// at so no sport's slot is missed. Kept for the cross-check that this union is
// a subset of the scheduler grid.
const ALL_HOURS = Object.freeze(
  [...new Set(ALL_SPORTS.flatMap((s) => SPORT_CADENCE[s].hours))].sort((a, b) => a - b),
);

/**
 * sportsForHour — which sports are scheduled to snapshot at this UTC hour.
 * @param {number} hour UTC hour 0..23
 * @param {string[]} [sports] restrict to this candidate set (defaults to all)
 * @returns {string[]}
 */
function sportsForHour(hour, sports = ALL_SPORTS) {
  const h = Number(hour);
  return sports.filter((s) => SPORT_CADENCE[s] && SPORT_CADENCE[s].hours.includes(h));
}

/** intradaySports — sports that opt into the 20-min intraday line refresh.
 *  Soccer is excluded on purpose (odds-api quota). */
function intradaySports(sports = ALL_SPORTS) {
  return sports.filter((s) => SPORT_CADENCE[s] && SPORT_CADENCE[s].intraday);
}

/** hoursFor — a single sport's snapshot hours (empty array if unknown). */
function hoursFor(sport) {
  const c = SPORT_CADENCE[String(sport || '').toLowerCase()];
  return c ? c.hours.slice() : [];
}

module.exports = {
  SPORT_CADENCE,
  ALL_SPORTS,
  ALL_HOURS,
  sportsForHour,
  intradaySports,
  hoursFor,
};
