/* ============================================================
   VYNDR — OUTLOOK MODE (Wave 4A, Step 3): the never-empty slate grid.

   The game grid must NEVER dead-end in a "NO SLATE" CTA. When there are no
   live games (and it's not a network failure) the grid falls back to REAL,
   always-available data — the terminal is never dark, but it is never
   fabricated either:
     • yesterday's PROVEN A-tier receipts (settled ledger hits), and/or
     • tomorrow's date-pinned ESPN schedule preview (free / cached).

   A network `fetchError` is DISTINCT and stays an ERROR state — a fetch
   failure is never dressed up as a fake outlook.

   Plain CommonJS so the .tsx surfaces import it (allowJs) AND Jest exercises
   the selection logic directly.
   ============================================================ */

const { buildHeroReceipts } = require('./slateAdapter');

/** Statuses that mean a game is no longer a PREVIEW (already underway/done). */
const NON_PREVIEW = new Set(['in', 'post', 'final', 'live', 'completed']);

/**
 * mapTomorrowPreview(scheduleGames, limit) — map real schedule games (either
 * the ESPN `{ awayTeam, homeTeam, gameTime, status }` shape OR the flattened
 * `{ away, home, start_time }` shape) → compact preview rows. Upcoming only;
 * a game missing either team is DROPPED (never fabricate a matchup).
 */
function mapTomorrowPreview(scheduleGames, limit = 8) {
  const list = Array.isArray(scheduleGames) ? scheduleGames : [];
  const out = [];
  for (const g of list) {
    if (!g) continue;
    const status = String(g.status || g.state || '').toLowerCase();
    if (NON_PREVIEW.has(status)) continue;
    const away = g.away || g.awayTeam?.name || g.awayTeam?.abbreviation || null;
    const home = g.home || g.homeTeam?.name || g.homeTeam?.abbreviation || null;
    if (!away || !home) continue; // absent beats a fabricated fixture
    out.push({
      id: g.id || `${away}-${home}`,
      away,
      home,
      time: g.gameTime || g.start_time || g.time || null,
      sport: g.sport ? String(g.sport).toUpperCase() : null,
    });
    if (out.length >= Math.max(0, limit)) break;
  }
  return out;
}

/**
 * buildOutlook(opts) →
 *   { mode: 'error' }                             — a network failure
 *   { mode: 'live' }                              — real games on the board
 *   { mode: 'outlook', receipts, tomorrow, hasContent }
 *
 * The outlook surface is ALWAYS non-error / non-blank at the surface level:
 * even with no receipts and no schedule, the caller still renders the
 * month-aware empty-state header — the grid never dead-ends in a CTA.
 *
 * @param {{ gamesCount?: number, fetchError?: unknown, settledRows?: unknown[], tomorrow?: unknown[] }} [opts]
 */
function buildOutlook(opts = {}) {
  const { gamesCount = 0, fetchError = null, settledRows = [], tomorrow = [] } = opts;
  if (fetchError) return { mode: 'error' };
  if (Number(gamesCount) > 0) return { mode: 'live' };

  const receipts = buildHeroReceipts(settledRows, 6);
  const preview = mapTomorrowPreview(tomorrow, 8);
  return {
    mode: 'outlook',
    receipts,
    tomorrow: preview,
    hasContent: receipts.length > 0 || preview.length > 0,
  };
}

module.exports = { buildOutlook, mapTomorrowPreview };
