import { useEffect, useMemo, useState } from 'react';

type Series = [string, number][];
interface EloHistoryFile {
  recentFrom: string;
  teams: Record<string, Series>;
}

let cache: Promise<EloHistoryFile | null> | null = null;
function loadHistory(): Promise<EloHistoryFile | null> {
  cache ??= fetch('/data/elohistory.json')
    .then((r) => (r.ok ? (r.json() as Promise<EloHistoryFile>) : null))
    .catch(() => null);
  return cache;
}

const periodT = (key: string): number => new Date(key.length === 4 ? `${key}-07-01` : `${key}-15`).getTime();

/** A century of strength in one line: the team's Elo trajectory. */
export function EloHistoryChart({ team }: { team: string }) {
  const [series, setSeries] = useState<Series | null>(null);

  useEffect(() => {
    let alive = true;
    void loadHistory().then((d) => alive && setSeries(d?.teams[team] ?? null));
    return () => { alive = false; };
  }, [team]);

  const W = 600;
  const H = 170;
  const PAD = { l: 38, r: 8, t: 8, b: 18 };

  const chart = useMemo(() => {
    if (!series || series.length < 2) return null;
    const t0 = periodT(series[0]![0]);
    const t1 = periodT(series[series.length - 1]![0]);
    const vals = series.map(([, v]) => v);
    const lo = Math.floor((Math.min(...vals) - 40) / 100) * 100;
    const hi = Math.ceil((Math.max(...vals) + 40) / 100) * 100;
    const x = (t: number) => PAD.l + ((t - t0) / Math.max(1, t1 - t0)) * (W - PAD.l - PAD.r);
    const y = (v: number) => PAD.t + (1 - (v - lo) / Math.max(1, hi - lo)) * (H - PAD.t - PAD.b);
    const line = series.map(([k, v]) => `${x(periodT(k)).toFixed(1)},${y(v).toFixed(1)}`).join(' ');
    const y0 = new Date(t0).getUTCFullYear();
    const y1 = new Date(t1).getUTCFullYear();
    const step = y1 - y0 > 80 ? 25 : y1 - y0 > 40 ? 20 : 10;
    const xTicks: { px: number; label: string }[] = [];
    for (let yr = Math.ceil(y0 / step) * step; yr <= y1; yr += step) {
      xTicks.push({ px: x(new Date(`${yr}-07-01`).getTime()), label: String(yr) });
    }
    const yTicks: { py: number; label: string }[] = [];
    for (let v = lo + 100; v < hi; v += Math.max(100, Math.round((hi - lo) / 4 / 100) * 100)) {
      yTicks.push({ py: y(v), label: String(v) });
    }
    return { line, xTicks, yTicks };
  }, [series]);

  if (!chart) return null;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="w-full" role="img" aria-label={`Elo · ${team}`}>
      <rect x={PAD.l} y={PAD.t} width={W - PAD.l - PAD.r} height={H - PAD.t - PAD.b} className="fill-[var(--app-elevated)]" rx={4} />
      {chart.yTicks.map((yt) => (
        <g key={yt.label}>
          <line x1={PAD.l} x2={W - PAD.r} y1={yt.py} y2={yt.py} className="stroke-[var(--app-line)]" strokeWidth={1} />
          <text x={PAD.l - 4} y={yt.py + 3} textAnchor="end" className="fill-[var(--app-faint)] text-[10px]">{yt.label}</text>
        </g>
      ))}
      <polyline points={chart.line} fill="none" className="stroke-[var(--app-accent)]" strokeWidth={2} strokeLinejoin="round" />
      {chart.xTicks.map((xt) => (
        <text key={xt.label} x={xt.px} y={H - 4} textAnchor="middle" className="fill-[var(--app-faint)] text-[10px]">{xt.label}</text>
      ))}
    </svg>
  );
}
