// Live-vs-LLM tracking chart — day by day since the live (real-money) fund
// started, its cumulative return against the LLM fund it mirrors. Both lines
// are rebased to 0% on the live start date, so the shaded band between them is
// the live fund's tracking error (deposit timing, fees, fills, an unsold name).
// Reads web/data/live_tracking.json (scripts/build_live_tracking.py). Styled to
// match PerformanceChart / AlphaChart (same W, grid, header, hover treatment).
function LiveTracking() {
  const [d, setD] = React.useState(null);
  const [hover, setHover] = React.useState(null);
  const svgRef = React.useRef(null);

  React.useEffect(() => {
    fetch(`data/live_tracking.json?t=${Date.now()}`, { cache: "no-store" })
      .then((r) => (r.ok ? r.json() : null))
      .then(setD)
      .catch(() => setD(null));
  }, []);

  const series = (d && d.series) || [];

  const W = 1000, H = 300;
  const PAD = { t: 24, r: 14, b: 30, l: 54 };
  const innerW = W - PAD.l - PAD.r;
  const innerH = H - PAD.t - PAD.b;

  if (series.length < 2) {
    return (
      <div style={{ height: 240, display: "flex", alignItems: "center", justifyContent: "center", color: "var(--ink-3)", fontFamily: "var(--mono)", fontSize: 12 }}>
        {d === null ? "Loading…" : "Tracking chart populates as the live fund accumulates days"}
      </div>
    );
  }

  const vals = series.flatMap((p) => [p.live_pct, p.llm_pct]).concat([0]);
  let lo = Math.min(...vals), hi = Math.max(...vals);
  const span = hi - lo || 1;
  lo -= span * 0.12; hi += span * 0.12;

  const x = (i) => PAD.l + (i / (series.length - 1)) * innerW;
  const y = (v) => PAD.t + (1 - (v - lo) / (hi - lo)) * innerH;
  const line = (key) => series.map((p, i) => `${i === 0 ? "M" : "L"} ${x(i).toFixed(2)} ${y(p[key]).toFixed(2)}`).join(" ");

  // Shaded band between the two lines = the tracking gap, the whole point.
  const band = line("live_pct") + " " +
    series.slice().reverse().map((p, i) => `L ${x(series.length - 1 - i).toFixed(2)} ${y(p.llm_pct).toFixed(2)}`).join(" ") + " Z";

  // y ticks: 4 evenly spaced, always including the 0% baseline.
  const ticks = [];
  for (let i = 0; i <= 4; i++) ticks.push(lo + ((hi - lo) * i) / 4);
  if (!ticks.some((t) => Math.abs(t) < (hi - lo) / 40)) ticks.push(0);

  const xTickCount = Math.min(6, series.length);
  const xTicks = [];
  for (let i = 0; i < xTickCount; i++) xTicks.push(Math.round((i * (series.length - 1)) / (xTickCount - 1)));

  const handleMove = (e) => {
    const rect = svgRef.current.getBoundingClientRect();
    const mx = ((e.clientX - rect.left) / rect.width) * W;
    const t = (Math.max(PAD.l, Math.min(W - PAD.r, mx)) - PAD.l) / innerW;
    setHover(Math.round(t * (series.length - 1)));
  };

  const latest = series[series.length - 1];
  const view = hover !== null ? series[hover] : latest;
  const sgn = (v) => (v >= 0 ? "+" : "");
  const cls = (v) => (v >= 0 ? "pos" : "neg");
  const fmtX = (s) => fmtDate(s, { style: "short" });

  return (
    <div>
      {/* Header — mirrors the NAV chart: hero return + inline comparison */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 20, marginBottom: 18 }}>
        <div>
          <div className="micro" style={{ marginBottom: 8 }}>
            {hover !== null ? fmtDate(view.date, { style: "long" }) : `Live fund return · since ${fmtDate(d.since, { style: "long" })}`}
          </div>
          <div style={{ display: "flex", alignItems: "baseline", gap: 14, flexWrap: "wrap" }}>
            <div className="serif tnum" style={{ fontSize: "clamp(30px, 4vw, 46px)", lineHeight: 1 }}>
              <span className={cls(view.live_pct)}>{sgn(view.live_pct)}{view.live_pct.toFixed(2)}%</span>
            </div>
            <div className="tnum" style={{ fontSize: 15 }}>
              <span className="muted">vs LLM </span>
              <span className={cls(view.llm_pct)}>{sgn(view.llm_pct)}{view.llm_pct.toFixed(2)}%</span>
              <span className="muted" style={{ marginLeft: 10 }}>· gap </span>
              <span className={cls(view.gap_pp)} style={{ fontWeight: 600 }}>{sgn(view.gap_pp)}{view.gap_pp.toFixed(2)}pp</span>
            </div>
          </div>
        </div>
      </div>

      <div className="chart-wrap">
        <svg
          ref={svgRef}
          viewBox={`0 0 ${W} ${H}`}
          className="chart-svg"
          preserveAspectRatio="none"
          onMouseMove={handleMove}
          onMouseLeave={() => setHover(null)}
          onTouchMove={(e) => { if (e.touches[0]) handleMove(e.touches[0]); }}
          onTouchEnd={() => setHover(null)}
          style={{ height: 300, cursor: "crosshair" }}
        >
          <defs>
            <linearGradient id="lt-band" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.16" />
              <stop offset="100%" stopColor="var(--accent)" stopOpacity="0.04" />
            </linearGradient>
          </defs>

          {/* y-grid (0% baseline drawn solid + stronger) */}
          {ticks.map((v, i) => {
            const zero = Math.abs(v) < (hi - lo) / 40;
            return (
              <g key={i}>
                <line x1={PAD.l} x2={W - PAD.r} y1={y(v)} y2={y(v)} stroke="var(--line)" strokeWidth={zero ? 1.5 : 1} strokeDasharray={zero ? "0" : "2 4"} opacity={zero ? 0.7 : 0.9} />
                <text x={PAD.l - 10} y={y(v) + 4} fontSize="11" fill="var(--ink-4)" textAnchor="end" fontFamily="var(--mono)">{sgn(v)}{v.toFixed(1)}%</text>
              </g>
            );
          })}

          {/* x labels */}
          {xTicks.map((idx, i) => (
            <text key={i} x={x(idx)} y={H - 9} fontSize="11" fill="var(--ink-4)" textAnchor="middle" fontFamily="var(--mono)">{fmtX(series[idx].date)}</text>
          ))}

          {/* tracking-gap band + the two lines */}
          <path d={band} fill="url(#lt-band)" />
          <path d={line("llm_pct")} fill="none" stroke="var(--ink-4)" strokeWidth="1.8" strokeDasharray="3 3" strokeLinejoin="round" strokeLinecap="round" opacity="0.95" />
          <path d={line("live_pct")} fill="none" stroke="var(--accent)" strokeWidth="2.4" strokeLinejoin="round" strokeLinecap="round" />

          {hover !== null && (
            <g>
              <line x1={x(hover)} x2={x(hover)} y1={PAD.t} y2={H - PAD.b} stroke="var(--ink-3)" strokeWidth="1" strokeDasharray="2 2" />
              <circle cx={x(hover)} cy={y(view.llm_pct)} r="4" fill="var(--bg-card)" stroke="var(--ink-4)" strokeWidth="1.8" />
              <circle cx={x(hover)} cy={y(view.live_pct)} r="5" fill="var(--bg-card)" stroke="var(--accent)" strokeWidth="2.4" />
            </g>
          )}
        </svg>
      </div>

      {/* legend — matches the NAV chart's swatch row */}
      <div style={{ display: "flex", gap: 22, marginTop: 14, fontSize: 12, flexWrap: "wrap" }} className="muted">
        <div style={{ display: "inline-flex", alignItems: "center", gap: 7 }}>
          <span style={{ display: "inline-block", width: 16, height: 3, background: "var(--accent)", borderRadius: 2 }} /> Live fund (real money)
        </div>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 7 }}>
          <span style={{ display: "inline-block", width: 16, height: 0, borderTop: "2px dashed var(--ink-4)" }} /> LLM fund (mirrored)
        </div>
        <div style={{ marginLeft: "auto", fontFamily: "var(--mono)", fontSize: 11 }}>
          both rebased to 0% on day one · gap = tracking error
        </div>
      </div>
    </div>
  );
}
