// ============================================================
// KPI strip — 4 headline metrics, each with inline sparkline
// Tufte: number + context (path, baseline, comparison)
// ============================================================

// Derives a daily P/L series from kelly backtest growth curve.
// growth_curve = [{date, bankroll}]. Returns daily delta units.
function dailyDeltas(growth) {
  if (!growth || growth.length < 2) return [];
  const out = [];
  for (let i = 1; i < growth.length; i++) {
    out.push({
      date: growth[i].date,
      delta: growth[i].bankroll - growth[i-1].bankroll,
      bankroll: growth[i].bankroll,
    });
  }
  return out;
}

// Returns calibration "health" score: lower Brier vs baseline = better.
// We display the *improvement over coin-flip baseline*, as a percentage.
function calibrationEdge(scalars) {
  if (!scalars || !scalars.brier || !scalars.brier_baseline) return null;
  return (scalars.brier_baseline - scalars.brier) / scalars.brier_baseline;
}

function KpiStrip({ w }) {
  // --- 1. ROI ---
  const roi = w.roi || {};
  const roiPct = roi.roi_pct != null ? roi.roi_pct / 100 : null;
  const profit = roi.total_profit_units;
  const bets = roi.total_bets;
  const wagered = roi.total_wagered_units;

  // --- 2. ML accuracy vs break-even ---
  const ml = w.ml_accuracy || {};
  const mlAcc = ml.accuracy;
  const mlBe = ml.break_even_accuracy ?? 0.524;
  const mlEdge = mlAcc != null && mlBe != null ? mlAcc - mlBe : null;

  // --- 3. CLV ---
  const clv = w.clv || {};
  const avgClv = clv.avg_clv;
  const posClvRate = clv.positive_clv_rate;

  // --- 4. Calibration (Brier improvement) ---
  const calEdge = calibrationEdge(w.calibration_scalars);
  const ece = w.calibration_scalars?.ece;
  const brier = w.calibration_scalars?.brier;

  // Daily sparkline series
  const growth = w.kelly_backtest?.variants?.full_kelly?.growth_curve || [];
  const startBR = w.kelly_backtest?.starting_bankroll ?? 100;
  const bankrollSeries = growth.map((d, i) => ({ x: i, y: d.bankroll }));

  // Daily ML hit rate (rolling 5-game window from .daily)
  const daily = w.daily || [];
  const mlRollingSeries = useMemo(() => {
    const out = [];
    const window = 5;
    for (let i = window - 1; i < daily.length; i++) {
      let games = 0, correct = 0;
      for (let j = i - window + 1; j <= i; j++) {
        games += daily[j].games || 0;
        correct += daily[j].ml_correct || 0;
      }
      out.push({ x: i, y: games > 0 ? correct / games : 0 });
    }
    return out;
  }, [daily]);

  // Daily P/L bars from growth curve
  const dailyPL = useMemo(() => {
    const d = dailyDeltas(growth);
    return d.slice(-30).map((p, i) => ({ x: i, y: p.delta }));
  }, [growth]);

  // Calibration buckets → dot-strip distribution
  const calBuckets = w.calibration || [];
  const calRows = calBuckets
    .filter(b => b.count > 0)
    .map(b => ({
      label: b.bucket,
      n: b.count,
      value: b.actual_win_rate,
      ref: b.avg_model_prob,
      color: Math.abs(b.calibration_error) < 0.05 ? colors.green : Math.abs(b.calibration_error) < 0.1 ? colors.amber : colors.red,
    }));

  return (
    <div className="kpi-strip">
      {/* ROI */}
      <div className="kpi">
        <div className="kpi-label">
          <span className="kpi-label-name">ROI</span>
          <Info tip="Return on amount wagered. Total profit ÷ total units staked. Positive = model is making money at quarter-Kelly sizing." />
        </div>
        <div className="kpi-meta">{bets} bets · {wagered ? wagered.toFixed(0) : '—'}u staked</div>
        <div className={'kpi-value ' + cls(roiPct)}>
          {roiPct == null ? '—' : (roiPct >= 0 ? '+' : '') + (roiPct * 100).toFixed(1) + '%'}
        </div>
        <div className="kpi-spark">
          <Sparkline
            data={bankrollSeries}
            width={260} height={28}
            stroke={(growth[growth.length-1]?.bankroll ?? startBR) >= startBR ? colors.green : colors.red}
            fill={(growth[growth.length-1]?.bankroll ?? startBR) >= startBR ? colors.green : colors.red}
            baselineY={startBR}
            endLabel={growth.length ? '$' + growth[growth.length-1].bankroll.toFixed(0) : null}
          />
        </div>
        <div className="kpi-foot">
          <span className="delta-vs">Profit</span>
          <span className={'delta-val ' + cls(profit)}>{fmt.units(profit, 1)}</span>
        </div>
      </div>

      {/* ML Accuracy */}
      <div className="kpi">
        <div className="kpi-label">
          <span className="kpi-label-name">Moneyline hit rate</span>
          <Info tip="% of moneyline picks that won. Break-even at standard -110 odds is 52.4% — anything below is unprofitable even if 'accurate'." />
        </div>
        <div className="kpi-meta">{ml.correct}/{ml.total_games} picks won</div>
        <div className={'kpi-value ' + (mlEdge == null ? 'neutral' : mlEdge >= 0 ? 'pos' : 'neg')}>
          {fmt.pct(mlAcc, 1)}
        </div>
        <div className="kpi-spark">
          <Sparkline
            data={mlRollingSeries}
            width={260} height={28}
            stroke={mlEdge >= 0 ? colors.green : colors.red}
            baselineY={mlBe}
          />
        </div>
        <div className="kpi-foot">
          <span className="delta-vs">vs break-even {(mlBe*100).toFixed(1)}%</span>
          <span className={'delta-val ' + cls(mlEdge)}>{fmt.pp(mlEdge)}</span>
        </div>
      </div>

      {/* CLV */}
      <div className="kpi">
        <div className="kpi-label">
          <span className="kpi-label-name">Avg CLV</span>
          <Info tip="Closing-Line Value. How much better your price was than the line at first pitch. Positive CLV is the single best long-term predictor of a betting edge." />
        </div>
        <div className="kpi-meta">{clv.clv_count || 0} resolved · closing-line value</div>
        <div className={'kpi-value ' + (avgClv == null ? 'neutral' : avgClv >= 0 ? 'pos' : 'neg')}>
          {avgClv == null ? '—' : (avgClv >= 0 ? '+' : '') + (avgClv * 100).toFixed(2) + 'pp'}
        </div>
        <div className="kpi-spark" style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 'auto' }}>
          {/* Two side-by-side mini gauges: % bets w/ +CLV, and accuracy on +edge bets */}
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 10, color: colors.fg3, fontFamily: 'var(--sb-font-mono)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
              +CLV rate
            </div>
            <div style={{ fontFamily: 'var(--sb-font-mono)', fontSize: 13, fontVariantNumeric: 'tabular-nums', marginTop: 2,
              color: posClvRate >= 0.5 ? colors.green : colors.red }}>
              {fmt.pct(posClvRate, 1)}
            </div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 10, color: colors.fg3, fontFamily: 'var(--sb-font-mono)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
              +Edge accuracy
            </div>
            <div style={{ fontFamily: 'var(--sb-font-mono)', fontSize: 13, fontVariantNumeric: 'tabular-nums', marginTop: 2 }}>
              {fmt.pct(clv.positive_edge_accuracy, 1)}
            </div>
          </div>
        </div>
        <div className="kpi-foot">
          <span className="delta-vs">Sharper than close</span>
          <span className={'delta-val ' + (avgClv >= 0 ? 'pos' : 'neg')}>
            {avgClv == null ? '—' : avgClv >= 0 ? 'Beats market' : 'Loses to market'}
          </span>
        </div>
      </div>

      {/* Calibration */}
      <div className="kpi">
        <div className="kpi-label">
          <span className="kpi-label-name">Calibration</span>
          <Info tip="How well model probabilities match reality. Brier score lower than coin-flip baseline (0.25) = informative. ECE = average gap between predicted and actual win rate." />
        </div>
        <div className="kpi-meta">ECE {fmt.pctRaw((ece ?? 0)*100, 1)} · Brier score</div>
        <div className={'kpi-value ' + (calEdge == null ? 'neutral' : calEdge >= 0 ? 'pos' : 'neg')}>
          {brier == null ? '—' : brier.toFixed(3)}
        </div>
        <div className="kpi-spark" style={{ marginTop: 'auto' }}>
          <DotStrip
            rows={calRows}
            vmin={0.3} vmax={0.8}
            width={260} height={22}
            refValue={0.5}
            color={colors.blue}
          />
          <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3, fontSize: 9, color: colors.fg3, fontFamily: 'var(--sb-font-mono)' }}>
            <span>30%</span><span>actual win rate by model-prob bucket</span><span>80%</span>
          </div>
        </div>
        <div className="kpi-foot">
          <span className="delta-vs">vs baseline {(0.25).toFixed(3)}</span>
          <span className={'delta-val ' + cls(calEdge)}>
            {calEdge == null ? '—' : (calEdge >= 0 ? '−' : '+') + Math.abs(calEdge*100).toFixed(1) + '%'}
          </span>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { KpiStrip, dailyDeltas });
