import { useEffect, useState, type ReactNode } from 'react';
import { Link } from '@tanstack/react-router';
import { Scale, Zap } from 'lucide-react';
import { PageHeader } from '@/components/ui/PageHeader';
import { Card, CardBody, CardHeader } from '@/components/ui/Card';
import { Term } from '@/components/ui/Term';
import { teamFlag } from '@/lib/teams';
import { fmt, fmtSplit, plural, useFormat, useT } from '@/lib/i18n';
import { cn } from '@/lib/cn';
import type { MatchProbs, ScoreboardData, ScoreboardRow } from '@/lib/types';

const pct = (x: number) => `${Math.round(x * 100)}%`;

function ProbTriple({ label, probs, tone }: { label: string; probs: MatchProbs; tone: 'model' | 'market' }) {
  const color = tone === 'model' ? 'bg-accent' : 'bg-gold';
  const split = `${pct(probs.home)} / ${pct(probs.draw)} / ${pct(probs.away)}`;
  return (
    <div className="flex items-center gap-2" title={`${label}: ${split}`} aria-label={`${label}: ${split}`}>
      {/* wide enough for "DraftKings" — both rows share the width so the bars align */}
      <span className={cn('w-20 shrink-0 text-[11px] font-bold uppercase tracking-wide', tone === 'model' ? 'text-accent' : 'text-gold')}>{label}</span>
      <div className="flex h-2 flex-1 overflow-hidden rounded-full bg-elevated">
        <div className={color} style={{ width: pct(probs.home) }} />
        <div className="bg-line-strong" style={{ width: pct(probs.draw) }} />
        <div className="bg-info" style={{ width: pct(probs.away) }} />
      </div>
      {/* the bar already carries the split — numbers hide on the narrowest phones */}
      <span className="tnum hidden w-24 shrink-0 text-right text-[11px] text-muted min-[420px]:inline">
        {pct(probs.home)} / {pct(probs.draw)} / {pct(probs.away)}
      </span>
    </div>
  );
}

function Row({ r }: { r: ScoreboardRow }) {
  const { t, kickoffDay, kickoffTime } = useFormat();
  const { scored } = r;
  const closer =
    scored && scored.marketRps != null
      ? scored.modelRps < scored.marketRps ? 'model' : scored.marketRps < scored.modelRps ? 'market' : 'tie'
      : null;
  return (
    <Card className={r.late ? 'opacity-60' : ''}>
      <CardBody className="space-y-2">
        <div className="flex flex-wrap items-center justify-between gap-2 text-sm">
          <Link to="/match/$num" params={{ num: String(r.num) }} className="flex items-center gap-2 font-medium text-ink hover:text-accent">
            <span aria-hidden>{teamFlag(r.home)}</span> {r.home}
            <span className="tnum text-faint">{r.status !== 'scheduled' && r.homeScore != null ? `${r.homeScore}–${r.awayScore}` : t.common.vs}</span>
            {r.away} <span aria-hidden>{teamFlag(r.away)}</span>
          </Link>
          <span className="text-[11px] text-faint">
            {r.group ? `${fmt(t.common.group, { group: r.group })} · ` : ''}{kickoffDay(r.kickoff)} {kickoffTime(r.kickoff)}
            {r.late && ` · ${t.scoreboard.row.lateNote}`}
          </span>
        </div>
        <ProbTriple label={t.scoreboard.row.modelLabel} probs={r.model} tone="model" />
        {r.market ? (
          <ProbTriple label={r.market.provider} probs={r.market.probs} tone="market" />
        ) : (
          <p className="text-[11px] text-faint">{t.scoreboard.row.noMarketLine}</p>
        )}
        {scored && (
          <div className="flex items-center gap-3 border-t border-line pt-2 text-[11px]">
            <span className="text-faint">
              {fmtSplit(t.scoreboard.row.result).map((p, i) =>
                typeof p === 'string' ? p : p.key === 'outcome' ? (
                  <span key={i} className="font-semibold text-ink">{t.outcome[scored.outcome]}</span>
                ) : null,
              )}
            </span>
            <span className="tnum text-muted">{fmt(t.scoreboard.row.modelRps, { rps: scored.modelRps })}</span>
            {scored.marketRps != null && <span className="tnum text-muted">{fmt(t.scoreboard.row.marketRps, { rps: scored.marketRps })}</span>}
            {closer && closer !== 'tie' && (
              <span className={cn('ml-auto rounded-full border px-2 py-0.5 font-bold uppercase tracking-wide', closer === 'model' ? 'border-accent/40 bg-accent-glow text-accent' : 'border-gold/40 bg-gold/15 text-gold')}>
                {closer === 'model' ? t.scoreboard.row.modelCloser : t.scoreboard.row.marketCloser}
              </span>
            )}
          </div>
        )}
      </CardBody>
    </Card>
  );
}

export function ScoreboardPage() {
  const t = useT();
  const [data, setData] = useState<ScoreboardData | null>(null);

  useEffect(() => {
    let alive = true;
    const load = () => fetch('/api/scoreboard').then((r) => r.json()).then((d: ScoreboardData) => alive && setData(d)).catch(() => {});
    void load();
    const id = setInterval(load, 30_000);
    return () => { alive = false; clearInterval(id); };
  }, []);

  const totals = data?.totals ?? null;
  const lead = totals ? (totals.modelRps < totals.marketRps ? 'model' : totals.marketRps < totals.modelRps ? 'market' : 'tie') : null;

  return (
    <div className="space-y-5">
      <PageHeader
        title={t.scoreboard.title}
        subtitle={t.scoreboard.subtitle}
      />

      <Card>
        <CardHeader className="flex items-center gap-2">
          <Scale size={16} className="text-accent" />
          <span className="font-display font-bold text-ink">{t.scoreboard.headToHead.title}</span>
        </CardHeader>
        <CardBody>
          {totals ? (
            <div className="grid grid-cols-3 items-center gap-3 text-center">
              <div>
                <div className={cn('font-display text-3xl font-extrabold', lead === 'model' ? 'text-accent' : 'text-ink')}>{totals.modelRps.toFixed(4)}</div>
                <div className="text-[11px] uppercase tracking-wide text-faint">{t.scoreboard.headToHead.modelLabel}</div>
                <div className="tnum mt-1 text-xs text-muted">{fmt(t.scoreboard.headToHead.closerTimes, { n: totals.modelCloser })}</div>
              </div>
              <div className="text-sm text-faint">
                {plural(t.scoreboard.headToHead.matchesScored, totals.n)}
                <div className="mt-1 text-xs">{lead === 'tie' ? t.scoreboard.headToHead.tie : lead === 'model' ? t.scoreboard.headToHead.modelAhead : t.scoreboard.headToHead.marketAhead}</div>
              </div>
              <div>
                <div className={cn('font-display text-3xl font-extrabold', lead === 'market' ? 'text-gold' : 'text-ink')}>{totals.marketRps.toFixed(4)}</div>
                <div className="text-[11px] uppercase tracking-wide text-faint">{t.scoreboard.headToHead.marketLabel}</div>
                <div className="tnum mt-1 text-xs text-muted">{fmt(t.scoreboard.headToHead.closerTimes, { n: totals.marketCloser })}</div>
              </div>
            </div>
          ) : (
            <p className="py-4 text-center text-sm text-muted">{t.scoreboard.headToHead.empty}</p>
          )}
          <p className="mt-3 border-t border-line pt-2 text-xs text-faint">
            {fmtSplit(t.scoreboard.rules.text).map((p, i) =>
              typeof p === 'string'
                ? p
                : (
                    {
                      devig: <Term key={i} k="de-vig" />,
                      rps: <Term key={i} k="RPS">{t.scoreboard.rules.rpsTerm}</Term>,
                    } as Record<string, ReactNode>
                  )[p.key] ?? null,
            )}
          </p>
        </CardBody>
      </Card>

      <Upsets rows={data?.rows ?? []} />

      {data ? (
        <div className="space-y-3">
          {data.rows.length === 0 && (
            <p className="py-8 text-center text-sm text-muted">{fmt(t.scoreboard.emptyRows, { minutes: 15 })}</p>
          )}
          {data.rows.map((r) => <Row key={r.num} r={r} />)}
        </div>
      ) : (
        <div className="h-48 animate-pulse rounded-xl border border-line bg-panel" />
      )}
    </div>
  );
}

/** The results the frozen model found least likely — the tournament's shocks. */
function Upsets({ rows }: { rows: ScoreboardRow[] }) {
  const t = useT();
  const upsets = rows
    .filter((r) => r.scored && !r.late)
    .map((r) => ({ r, p: r.model[r.scored!.outcome] }))
    .filter((u) => u.p < 0.30)
    .sort((a, b) => a.p - b.p)
    .slice(0, 5);
  if (upsets.length === 0) return null;
  return (
    <Card>
      <CardHeader className="flex items-center gap-2">
        <Zap size={16} className="text-gold" />
        <span className="font-display font-bold text-ink">{t.scoreboard.upsets.title}</span>
      </CardHeader>
      <CardBody>
        <ul className="space-y-2">
          {upsets.map(({ r, p }) => (
            <li key={r.num}>
              <Link to="/match/$num" params={{ num: String(r.num) }} className="flex flex-wrap items-center gap-2 text-sm text-ink hover:text-accent">
                <span aria-hidden>{teamFlag(r.home)}</span>
                <span className="font-medium">{r.home}</span>
                <span className="tnum text-faint">{r.homeScore}–{r.awayScore}</span>
                <span className="font-medium">{r.away}</span>
                <span aria-hidden>{teamFlag(r.away)}</span>
                <span className="ml-auto rounded-full border border-gold/40 bg-gold/10 px-2 py-0.5 text-[11px] font-bold text-gold">
                  {fmt(t.scoreboard.upsets.chance, { pct: `${Math.max(1, Math.round(p * 100))}%` })}
                </span>
              </Link>
            </li>
          ))}
        </ul>
      </CardBody>
    </Card>
  );
}
