import { useEffect, useMemo, useState } from 'react';
import { Link, useParams } from '@tanstack/react-router';
import { ArrowLeft, ArrowRight, BadgeCheck, Ban, Goal, Shield, Shirt, Stethoscope } from 'lucide-react';
import { Badge } from '@/components/ui/Badge';
import { Card, CardBody, CardHeader } from '@/components/ui/Card';
import { WinProbBar } from '@/components/WinProbBar';
import { WinProbTimeline, type TimelinePoint } from '@/components/WinProbTimeline';
import { FormChips } from '@/components/FormChips';
import { XgRace } from '@/components/XgRace';
import { ShotMap } from '@/components/ShotMap';
import { MomentumStrip } from '@/components/MomentumStrip';
import { EventIcon, MatchTimeline } from '@/components/MatchTimeline';
import { LineupPitch } from '@/components/LineupPitch';
import { teamFlag } from '@/lib/teams';
import { fmt, useFormat, useT } from '@/lib/i18n';
import { goalEvents, shootoutKicks } from '@/lib/matchEvents';
import { redCards } from '@/lib/discipline';
import { inPlayProbs } from '@/lib/model/inplay';
import { useTournamentStore } from '@/stores/tournamentStore';
import { PlayerLink } from '@/components/PlayerLink';
import type { Fixture, KeyPlayer, MatchPreview, MatchRich } from '@/lib/types';

const num = (s: string | undefined) => (s ? Number(s.replace('%', '')) || 0 : 0);

/** Label dict for the detailed-stats card, widened for lookup by stat key. */
const fullStatLabels = (d: Record<string, string>): Record<string, string> => d;

type TabKey = 'summary' | 'timeline' | 'stats' | 'lineups';

function LiveStatRow({ label, home, away }: { label: string; home: number; away: number }) {
  const total = home + away || 1;
  return (
    <div>
      <div className="flex items-center justify-between text-sm">
        <span className="tnum font-bold text-accent">{home}</span>
        <span className="text-xs uppercase tracking-wide text-faint">{label}</span>
        <span className="tnum font-bold text-info">{away}</span>
      </div>
      <div className="mt-1 flex h-1.5 overflow-hidden rounded-full bg-elevated">
        <div className="bg-accent" style={{ width: `${(home / total) * 100}%` }} />
        <div className="ml-auto bg-info" style={{ width: `${(away / total) * 100}%` }} />
      </div>
    </div>
  );
}

function ScorerList({ team, players }: { team: string; players: KeyPlayer[] }) {
  const t = useT();
  return (
    <div>
      <div className="mb-2 flex items-center gap-2 text-sm font-semibold text-ink"><span aria-hidden>{teamFlag(team)}</span> {team}</div>
      {players.length ? (
        <ul className="space-y-1">
          {players.slice(0, 6).map((p) => (
            <li key={p.name} className="flex items-center justify-between text-sm">
              <PlayerLink name={p.name} className="truncate text-ink-soft transition-colors hover:text-accent" />
              <span className="tnum shrink-0 text-faint">{p.goals}{p.pens ? ` (${fmt(t.common.pensShort, { n: p.pens })})` : ''}</span>
            </li>
          ))}
        </ul>
      ) : <p className="text-xs text-faint">{t.common.noData}</p>}
    </div>
  );
}

function LineupCol({ team, players }: { team: string; players: { name: string; position: string | null; number: number | null; starter: boolean }[] }) {
  const starters = players.filter((p) => p.starter);
  const list = starters.length ? starters : players;
  return (
    <div>
      <div className="mb-2 text-sm font-semibold text-ink">{team}</div>
      <ul className="space-y-0.5 text-sm">
        {list.map((p) => (
          <li key={p.name} className="flex items-center gap-2 text-ink-soft">
            <span className="tnum w-5 text-right text-xs text-faint">{p.number ?? ''}</span>
            <PlayerLink name={p.name} className="truncate transition-colors hover:text-accent" />
            <span className="ml-auto text-[11px] text-faint">{p.position}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}

/** Hero stat chip: faint label · mono value. */
function HeroChip({ label, value, gold }: { label: string; value: string; gold?: boolean }) {
  return (
    <span className="inline-flex max-w-full items-center gap-1.5 rounded-full bg-elevated px-3 py-1 text-xs">
      <span className="shrink-0 text-faint">{label}</span>
      <span className={`tnum truncate ${gold ? 'text-gold' : 'text-ink-soft'}`}>{value}</span>
    </span>
  );
}

export function MatchPreviewPage() {
  const { num: numParam } = useParams({ strict: false }) as { num: string };
  const { t, locale, kickoffDay, kickoffTime } = useFormat();
  const [preview, setPreview] = useState<MatchPreview | null>(null);
  const [timeline, setTimeline] = useState<TimelinePoint[]>([]);
  const [rich, setRich] = useState<MatchRich | null>(null);
  const [failed, setFailed] = useState(false);
  const [activeTab, setActiveTab] = useState<TabKey>('summary');

  // Live score/minute arrive over the WebSocket snapshot — overlay them on the
  // (less-frequently-fetched) preview.
  const liveFixture = useTournamentStore((s) => s.snapshot?.fixtures.find((f) => f.num === Number(numParam)));
  const isLive = (liveFixture?.status ?? preview?.fixture.status) === 'live';

  useEffect(() => {
    let alive = true;
    setPreview(null);
    setTimeline([]);
    setRich(null);
    setFailed(false);
    setActiveTab('summary');
    const load = () =>
      fetch(`/api/preview/${numParam}`)
        .then((r) => (r.ok ? r.json() : Promise.reject()))
        .then((d: MatchPreview) => alive && setPreview(d))
        .catch(() => alive && setFailed(true));
    const loadTimeline = () =>
      fetch(`/api/inplay/${numParam}`)
        .then((r) => (r.ok ? r.json() : Promise.reject()))
        .then((d: { points: TimelinePoint[] }) => alive && setTimeline(d.points))
        .catch(() => {});
    const loadRich = () =>
      fetch(`/api/match-rich/${numParam}`)
        .then((r) => (r.ok ? r.json() : Promise.reject()))
        .then((d: MatchRich) => alive && setRich(d))
        .catch(() => {});
    void load();
    void loadTimeline();
    void loadRich();
    const id = setInterval(() => {
      if (useTournamentStore.getState().snapshot?.fixtures.find((f) => f.num === Number(numParam))?.status === 'live') {
        void load();
        void loadTimeline();
        void loadRich();
      }
    }, 10_000);
    return () => { alive = false; clearInterval(id); };
  }, [numParam]);

  const f: Fixture | undefined = liveFixture ?? preview?.fixture;

  const inPlay = useMemo(() => {
    if (!preview?.prediction || !f || f.status !== 'live' || f.homeScore == null || f.awayScore == null) return null;
    const reds = redCards(preview.events);
    return inPlayProbs(preview.prediction.lambdaHome, preview.prediction.lambdaAway, f.minute ?? 0, f.homeScore, f.awayScore, reds.home, reds.away);
  }, [preview, f]);

  const statRows = useMemo<[string, string][]>(() => [
    ['possessionPct', t.match.stats.possessionPct],
    ['totalShots', t.match.stats.totalShots],
    ['shotsOnTarget', t.match.stats.shotsOnTarget],
    ['wonCorners', t.match.stats.wonCorners],
    ['foulsCommitted', t.match.stats.foulsCommitted],
    ['saves', t.match.stats.saves],
  ], [t]);

  const goals = useMemo(() => (preview ? goalEvents(preview.events) : []), [preview]);
  const kicks = useMemo(() => (preview ? shootoutKicks(preview.events) : []), [preview]);

  if (failed) return <div className="py-16 text-center text-muted">{t.match.loadError} <Link to="/" className="text-accent">{t.match.backToLive}</Link></div>;
  if (!preview || !f) return <div className="h-96 animate-pulse rounded-2xl border border-line bg-panel" />;

  const hasScore = f.status === 'live' || f.status === 'finished';
  const homeName = f.home.label;
  const awayName = f.away.label;
  const finished = f.status === 'finished';

  // Hero extras from the rich capture: kickoff-hour weather (pre-match only)
  // and post-match official chips (attendance, referee, player of the match).
  const wx = f.status === 'scheduled' ? rich?.weather : null;
  const weatherText = wx && wx.tempC != null && wx.precipProbPct != null && wx.windKmh != null
    ? fmt(t.match.weatherLine, { temp: Math.round(wx.tempC), precip: Math.round(wx.precipProbPct), wind: Math.round(wx.windKmh) })
    : null;
  const altitudeM = wx && wx.elevationM >= 1000 ? Math.round(wx.elevationM) : null;
  const infoText = rich?.info && rich.info.stadium && rich.info.attendance != null && rich.info.referee && f.status === 'scheduled'
    ? fmt(t.match.attendanceLine, { stadium: rich.info.stadium, n: rich.info.attendance.toLocaleString(locale), ref: rich.info.referee })
    : null;
  const tvText = !finished && preview.broadcasts.length > 0
    ? fmt(t.match.tvLine, { channels: preview.broadcasts.join(' · ') })
    : null;

  const heroChips: { label: string; value: string; gold?: boolean }[] = [];
  if (hasScore) {
    if (rich?.xg) heroChips.push({ label: 'xG', value: `${rich.xg.home.toFixed(2)}–${rich.xg.away.toFixed(2)}` });
    if (isLive && preview.liveStats) {
      const ls = preview.liveStats;
      if (ls.home.possessionPct != null || ls.away.possessionPct != null) {
        heroChips.push({ label: t.match.chips.poss, value: `${num(ls.home.possessionPct)}%–${num(ls.away.possessionPct)}%` });
      }
      if (ls.home.totalShots != null || ls.away.totalShots != null) {
        heroChips.push({ label: t.match.chips.shots, value: `${num(ls.home.totalShots)}–${num(ls.away.totalShots)}` });
      }
    }
    if (finished) {
      if (rich?.potm) heroChips.push({ label: t.match.potm, value: rich.potm.rating != null ? `${rich.potm.name} · ${rich.potm.rating}` : rich.potm.name, gold: true });
      if (rich?.info?.attendance != null) heroChips.push({ label: t.match.chips.att, value: rich.info.attendance.toLocaleString(locale) });
      if (rich?.info?.referee) heroChips.push({ label: t.match.chips.ref, value: rich.info.referee });
    }
  }

  // Tabs only appear when their data exists (e.g. no Timeline before kickoff).
  const tabs: TabKey[] = ['summary'];
  if (preview.events.length > 0) tabs.push('timeline');
  if (preview.liveStats || (rich && ((rich.fullStats?.length ?? 0) > 0 || rich.zones != null || rich.shots.length >= 3 || rich.momentum.length >= 10))) tabs.push('stats');
  tabs.push('lineups');
  const tab: TabKey = tabs.includes(activeTab) ? activeTab : 'summary';

  const modelCard = preview.prediction && (
    <Card>
      <CardHeader><span className="font-display font-bold text-ink">{hasScore ? t.match.preMatchModel : t.match.modelExpectation}</span></CardHeader>
      <CardBody className="space-y-2">
        <WinProbBar home={preview.prediction.home} away={preview.prediction.away} probs={preview.prediction.probs} topScore={preview.prediction.topScore} />
        <p className="text-xs text-faint">
          {finished && f.homeScore != null && f.awayScore != null
            ? fmt(t.match.predictedVsActual, {
                ph: preview.prediction.topScore.home,
                pa: preview.prediction.topScore.away,
                ah: f.homeScore,
                aa: f.awayScore,
              })
            : t.match.modelHonestyNote}
        </p>
      </CardBody>
    </Card>
  );

  return (
    <div className="space-y-5">
      <Link to="/" className="inline-flex items-center gap-1.5 text-sm text-muted hover:text-ink"><ArrowLeft size={15} /> {t.common.back}</Link>

      {/* hero scoreboard */}
      <div className={`relative overflow-hidden rounded-2xl border bg-gradient-to-b from-panel to-surface p-6 md:p-8 ${isLive ? 'border-live/40 ring-1 ring-live/30' : 'border-line'}`}>
        <div aria-hidden className="pointer-events-none absolute inset-0 bg-[radial-gradient(120%_90%_at_50%_-20%,var(--app-accent-glow),transparent_60%)]" />
        <div className="relative">
          <div className="smallcaps text-center">
            {f.group ? fmt(t.common.group, { group: f.group }) : t.stage[f.stage]}
            <span className="text-line-strong"> · </span>{kickoffDay(f.kickoff)}
            <span className="text-line-strong"> · </span>{kickoffTime(f.kickoff)}
            <span className="text-line-strong"> · </span>
            {f.venue ? (
              <Link to="/venue/$name" params={{ name: f.venue }} className="whitespace-nowrap transition-colors hover:text-accent">{preview.venue}</Link>
            ) : (
              <span className="whitespace-nowrap">{preview.venue}</span>
            )}
          </div>
          <div className="mt-5 grid grid-cols-[1fr_auto_1fr] items-center gap-2 md:gap-6">
            <Link to="/team/$name" params={{ name: f.home.team ?? '' }} className="flex flex-col items-center gap-1.5 hover:opacity-80">
              <span aria-hidden className="text-4xl md:text-6xl">{f.home.team ? teamFlag(f.home.team) : <Shield size={40} className="text-faint" />}</span>
              <span className="text-center text-[15px] font-bold text-ink md:text-lg">{homeName}</span>
            </Link>
            <div className="text-center">
              {hasScore ? (
                <div className="tnum text-[40px] font-semibold leading-none tracking-[-0.04em] text-ink md:text-6xl">
                  {f.homeScore ?? 0}<span className="text-[0.5em] text-line-strong">–</span>{f.awayScore ?? 0}
                </div>
              ) : (
                <div className="tnum text-2xl font-bold text-muted md:text-3xl">{kickoffTime(f.kickoff)}</div>
              )}
              {isLive && <div className="mt-2 inline-flex items-center gap-1.5 text-[11px] font-bold uppercase text-live"><span className="live-dot h-1.5 w-1.5 rounded-full bg-live" />{f.minute ? fmt(t.live.minute, { n: f.minute }) : t.common.liveNow}</div>}
              {finished && <div className="mt-2 text-[11px] font-bold uppercase tracking-wider text-faint">{t.common.fullTime}</div>}
            </div>
            <Link to="/team/$name" params={{ name: f.away.team ?? '' }} className="flex flex-col items-center gap-1.5 hover:opacity-80">
              <span aria-hidden className="text-4xl md:text-6xl">{f.away.team ? teamFlag(f.away.team) : <Shield size={40} className="text-faint" />}</span>
              <span className="text-center text-[15px] font-bold text-ink md:text-lg">{awayName}</span>
            </Link>
          </div>
          {heroChips.length > 0 && (
            <div className="mt-5 flex flex-wrap items-center justify-center gap-2 border-t border-line pt-4">
              {heroChips.map((c) => <HeroChip key={c.label} label={c.label} value={c.value} gold={c.gold ?? false} />)}
            </div>
          )}
          {(weatherText || infoText || tvText) && (
            <div className="mt-5 space-y-1 border-t border-line pt-3 text-center text-xs text-muted">
              {weatherText && (
                <div className="flex flex-wrap items-center justify-center gap-2">
                  <span>{weatherText}</span>
                  {altitudeM != null && <Badge tone="muted">{fmt(t.match.altitude, { m: altitudeM })}</Badge>}
                </div>
              )}
              {infoText && <div>{infoText}</div>}
              {tvText && <div>{tvText}</div>}
            </div>
          )}
        </div>
      </div>

      {/* sticky sub-nav */}
      <div className="sticky top-14 z-20 bg-surface/90 py-1 backdrop-blur">
        <div className="flex gap-1 overflow-x-auto rounded-xl border border-line bg-panel p-1" role="tablist">
          {tabs.map((k) => (
            <button
              key={k}
              role="tab"
              aria-selected={tab === k}
              onClick={() => setActiveTab(k)}
              className={`flex-1 whitespace-nowrap rounded-lg px-3 py-2 text-sm font-semibold transition-colors ${tab === k ? 'bg-panel-2 text-ink shadow-sm' : 'text-muted hover:text-ink-soft'}`}
            >
              {t.match.tabs[k]}
            </button>
          ))}
        </div>
      </div>

      {/* ── Summary ── */}
      {tab === 'summary' && (
        <div className="space-y-4">
          <div className="grid items-start gap-4 md:grid-cols-2">
            {inPlay && preview.prediction ? (
              <Card className="border-live/30">
                <CardHeader className="flex items-center gap-2">
                  <span className="live-dot h-2 w-2 rounded-full bg-live" />
                  <span className="font-display font-bold text-ink">{t.match.liveWinProbability}</span>
                </CardHeader>
                <CardBody>
                  <WinProbBar home={homeName} away={awayName} probs={inPlay} />
                  {timeline.length >= 2 && (
                    <div className="mt-4">
                      <WinProbTimeline points={timeline} home={homeName} away={awayName} />
                    </div>
                  )}
                  <p className="mt-2 text-xs text-faint">{t.match.inPlayHelp}</p>
                </CardBody>
              </Card>
            ) : modelCard}
            {f.status === 'scheduled' && preview.scorerProps.length > 0 && (
              <Card>
                <CardHeader className="flex items-center gap-2">
                  <Goal size={16} className="text-accent" />
                  <span className="font-display font-bold text-ink">{t.match.whoScores.title}</span>
                </CardHeader>
                <CardBody>
                  <ul className="space-y-1.5">
                    {preview.scorerProps.map((p) => (
                      <li key={p.player} className="flex items-center gap-2 text-sm">
                        <PlayerLink name={p.player} className="truncate font-medium text-ink transition-colors hover:text-accent" />
                        <span className="tnum ml-auto shrink-0 rounded-full bg-elevated px-2 py-0.5 text-xs font-semibold text-ink-soft">
                          {p.odds > 0 ? `+${p.odds}` : p.odds}
                        </span>
                      </li>
                    ))}
                  </ul>
                  <p className="mt-2 text-xs text-faint">{t.match.whoScores.note}</p>
                </CardBody>
              </Card>
            )}
            {preview.events.length > 0 && (
              <Card>
                <CardHeader><span className="font-display font-bold text-ink">{t.match.keyMoments}</span></CardHeader>
                <CardBody>
                  {goals.length ? (
                    <div className="space-y-2.5">
                      {goals.map((g, i) => (
                        <div key={i} className="flex items-center gap-2 text-sm">
                          <span className="tnum w-8 shrink-0 text-xs text-faint">{g.minute != null ? fmt(t.live.minute, { n: g.minute }) : ''}</span>
                          <span aria-hidden className={`h-1.5 w-1.5 shrink-0 rounded-full ${g.side === 'away' ? 'bg-info' : 'bg-accent'}`} />
                          <EventIcon kind="goal" />
                          <span className="truncate font-medium text-ink-soft">{g.title}</span>
                          {g.score && <span className="tnum ml-auto shrink-0 text-xs text-faint">{g.score[0]}–{g.score[1]}</span>}
                        </div>
                      ))}
                    </div>
                  ) : (
                    <p className="text-sm text-faint">{t.match.noGoalsYet}</p>
                  )}
                  <button onClick={() => setActiveTab('timeline')} className="mt-3 inline-flex items-center gap-1 text-sm font-semibold text-accent hover:underline">
                    {t.match.viewTimeline} <ArrowRight size={14} />
                  </button>
                </CardBody>
              </Card>
            )}
          </div>
          {kicks.length > 0 && (
            <Card className="border-gold/40">
              <CardHeader className="flex items-center gap-2">
                <Goal size={16} className="text-gold" />
                <span className="font-display font-bold text-ink">{t.match.shootoutTitle}</span>
              </CardHeader>
              <CardBody className="space-y-2">
                {(['home', 'away'] as const).map((side) => {
                  const sideKicks = kicks.filter((k) => k.side === side);
                  if (!sideKicks.length) return null;
                  const team = side === 'home' ? f.home.team : f.away.team;
                  return (
                    <div key={side} className="flex items-center gap-2.5 text-sm">
                      <span className="flex w-32 shrink-0 items-center gap-1.5 font-medium text-ink">
                        {team && <span aria-hidden>{teamFlag(team)}</span>}
                        <span className="truncate">{side === 'home' ? homeName : awayName}</span>
                      </span>
                      <span className="flex flex-wrap items-center gap-1">
                        {sideKicks.map((k, i) => (
                          <span
                            key={i}
                            title={k.player ?? ''}
                            className={`h-3 w-3 rounded-full ${k.scored ? 'bg-accent' : 'border-2 border-loss'}`}
                          />
                        ))}
                      </span>
                      <span className="tnum ml-auto shrink-0 font-bold text-ink">{sideKicks.filter((k) => k.scored).length}</span>
                    </div>
                  );
                })}
                <p className="text-xs text-faint">{t.match.shootoutNote}</p>
              </CardBody>
            </Card>
          )}
          {/* live matches keep the pre-match view alongside the in-play one */}
          {inPlay && preview.prediction && modelCard}
          {finished && timeline.length >= 2 && (
            <Card>
              <CardHeader><span className="font-display font-bold text-ink">{t.match.momentum}</span></CardHeader>
              <CardBody>
                <WinProbTimeline points={timeline} home={homeName} away={awayName} />
              </CardBody>
            </Card>
          )}
        </div>
      )}

      {/* ── Timeline ── */}
      {tab === 'timeline' && preview.events.length > 0 && (
        <Card>
          <CardBody className="px-2 sm:px-4">
            <MatchTimeline events={preview.events} commentary={preview.commentary} shots={rich?.shots ?? []} momentum={rich?.momentum ?? []} report={preview.report?.story ?? ''} status={f.status} minute={f.minute} homeScore={f.homeScore} awayScore={f.awayScore} />
          </CardBody>
        </Card>
      )}

      {/* ── Stats ── */}
      {tab === 'stats' && (
        <div className="grid items-start gap-4 md:grid-cols-2">
          {preview.liveStats && (
            <Card>
              <CardHeader><span className="font-display font-bold text-ink">{t.match.statsTitle}</span></CardHeader>
              <CardBody className="space-y-3">
                {statRows.filter(([k]) => preview.liveStats!.home[k] != null || preview.liveStats!.away[k] != null).map(([k, label]) => (
                  <LiveStatRow key={k} label={label} home={num(preview.liveStats!.home[k])} away={num(preview.liveStats!.away[k])} />
                ))}
              </CardBody>
            </Card>
          )}
          {rich?.fullStats && rich.fullStats.length > 0 && (
            <Card>
              <CardHeader><span className="font-display font-bold text-ink">{t.match.fullStatsTitle}</span></CardHeader>
              <CardBody>
                <div className="space-y-2">
                  {rich.fullStats.map((r) => (
                    <div key={r.key} className="grid grid-cols-[1fr_auto_1fr] items-center gap-2 text-sm">
                      <span className="tnum font-semibold text-ink">{r.home}</span>
                      <span className="text-center text-xs text-muted">{fullStatLabels(t.match.fullStats)[r.key] ?? r.key}</span>
                      <span className="tnum text-right font-semibold text-ink">{r.away}</span>
                    </div>
                  ))}
                </div>
                <p className="mt-2 text-xs text-faint">{t.match.xgAttribution}</p>
              </CardBody>
            </Card>
          )}
          {rich?.zones && (
            <Card>
              <CardHeader><span className="font-display font-bold text-ink">{t.match.zonesTitle}</span></CardHeader>
              <CardBody className="space-y-3">
                {([
                  ['home', homeName, rich.zones.home, ['bg-accent/40', 'bg-accent/70', 'bg-accent']],
                  ['away', awayName, rich.zones.away, ['bg-info/40', 'bg-info/70', 'bg-info']],
                ] as const).map(([side, name, z, tones]) => {
                  const total = z.left + z.center + z.right || 1;
                  return (
                    <div key={side}>
                      <div className="mb-1 text-sm font-medium text-ink">{name}</div>
                      <div className="flex h-3 overflow-hidden rounded-full bg-elevated">
                        <div className={tones[0]} style={{ width: `${(z.left / total) * 100}%` }} />
                        <div className={tones[1]} style={{ width: `${(z.center / total) * 100}%` }} />
                        <div className={tones[2]} style={{ width: `${(z.right / total) * 100}%` }} />
                      </div>
                      <div className="mt-0.5 flex justify-between text-[10px] text-faint">
                        <span>{t.match.zones.left} {z.left}%</span>
                        <span>{t.match.zones.center} {z.center}%</span>
                        <span>{t.match.zones.right} {z.right}%</span>
                      </div>
                    </div>
                  );
                })}
                <p className="text-xs text-faint">{t.match.zonesNote}</p>
              </CardBody>
            </Card>
          )}
          {rich && rich.momentum.length >= 10 && (
            <Card>
              <CardHeader><span className="font-display font-bold text-ink">{t.match.momentumTitle}</span></CardHeader>
              <CardBody>
                <MomentumStrip points={rich.momentum} home={homeName} away={awayName} />
              </CardBody>
            </Card>
          )}
          {rich && rich.shots.length >= 3 && (
            <>
              <Card>
                <CardHeader className="flex items-center justify-between">
                  <span className="font-display font-bold text-ink">{t.match.xgRace}</span>
                  {rich.xg && (
                    <span className="tnum text-sm font-bold">
                      <span className="text-accent">{rich.xg.home.toFixed(2)}</span>
                      <span className="font-normal text-faint"> – </span>
                      <span className="text-info">{rich.xg.away.toFixed(2)}</span>
                    </span>
                  )}
                </CardHeader>
                <CardBody>
                  <XgRace shots={rich.shots} home={homeName} away={awayName} />
                </CardBody>
              </Card>
              <Card>
                <CardHeader><span className="font-display font-bold text-ink">{t.match.shotMap}</span></CardHeader>
                <CardBody>
                  <ShotMap shots={rich.shots} home={homeName} away={awayName} />
                  <p className="mt-2 text-xs text-faint">{t.match.xgAttribution}</p>
                </CardBody>
              </Card>
            </>
          )}
        </div>
      )}

      {/* ── Lineups ── */}
      {tab === 'lineups' && (
        <div className="space-y-4">
          {(preview.suspensions.home.length > 0 || preview.suspensions.away.length > 0 ||
            preview.injuries.home.length > 0 || preview.injuries.away.length > 0) && (
            <Card className="border-loss/30">
              <CardBody className="space-y-1.5 text-sm">
                {([['home', preview.suspensions.home], ['away', preview.suspensions.away]] as const)
                  .filter(([, players]) => players.length > 0)
                  .map(([side, players]) => (
                    <div key={side} className="flex items-center gap-2 text-ink-soft">
                      <Ban size={14} className="shrink-0 text-loss" />
                      <span aria-hidden>{(side === 'home' ? f.home.team : f.away.team) ? teamFlag((side === 'home' ? f.home.team : f.away.team)!) : ''}</span>
                      <span>{fmt(t.match.suspended, { players: players.join(', ') })}</span>
                    </div>
                  ))}
                {(['home', 'away'] as const)
                  .filter((side) => preview.injuries[side].length > 0)
                  .map((side) => (
                    <div key={`inj-${side}`} className="flex items-center gap-2 text-ink-soft">
                      <Stethoscope size={14} className="shrink-0 text-gold" />
                      <span aria-hidden>{(side === 'home' ? f.home.team : f.away.team) ? teamFlag((side === 'home' ? f.home.team : f.away.team)!) : ''}</span>
                      <span>
                        {fmt(t.match.unavailable, {
                          players: preview.injuries[side].map((i) => (i.reason ? `${i.player} (${i.reason})` : i.player)).join(', '),
                        })}
                      </span>
                    </div>
                  ))}
              </CardBody>
            </Card>
          )}
          {/* Before kickoff the pitch shows FotMob's projected XIs, clearly
              labeled as predicted; from kickoff it's the confirmed lineup. */}
          {rich?.lineup ? (
            <Card>
              <CardHeader className="flex items-center gap-2">
                <Shirt size={16} className="text-accent" />
                <span className="font-display font-bold text-ink">{hasScore || rich.lineupConfirmed ? t.match.lineups : t.match.predictedLineups}</span>
                {rich.lineupConfirmed && !finished && (
                  <span className="ml-auto flex items-center gap-1 rounded-full bg-accent/10 px-2 py-0.5 text-[11px] font-semibold text-accent">
                    <BadgeCheck size={12} /> {t.match.confirmedLineups}
                  </span>
                )}
              </CardHeader>
              <CardBody>
                <LineupPitch lineup={rich.lineup} home={homeName} away={awayName} events={preview.events} mode={isLive ? 'current' : 'starters'} />
                <p className="mt-2 text-xs text-faint">{hasScore || rich.lineupConfirmed ? t.match.xgAttribution : t.match.predictedLineupsNote}</p>
              </CardBody>
            </Card>
          ) : (
            <Card>
              <CardHeader className="flex items-center gap-2"><Shirt size={16} className="text-accent" /><span className="font-display font-bold text-ink">{preview.lineups ? t.match.lineups : t.match.keyPlayers}</span></CardHeader>
              <CardBody className="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-6">
                {preview.lineups ? (
                  <><LineupCol team={homeName} players={preview.lineups.home} /><LineupCol team={awayName} players={preview.lineups.away} /></>
                ) : (
                  <><ScorerList team={homeName} players={preview.keyPlayers.home} /><ScorerList team={awayName} players={preview.keyPlayers.away} /></>
                )}
              </CardBody>
            </Card>
          )}
          <div className="grid items-start gap-4 md:grid-cols-2">
            {(preview.form.home.length > 0 || preview.form.away.length > 0) && (
              <Card>
                <CardHeader><span className="font-display font-bold text-ink">{t.match.recentForm}</span></CardHeader>
                <CardBody className="space-y-3">
                  <div className="flex items-center justify-between gap-2"><span className="flex min-w-0 items-center gap-2 text-sm font-medium text-ink"><span className="shrink-0">{f.home.team && teamFlag(f.home.team)}</span> <span className="truncate">{homeName}</span></span><FormChips form={preview.form.home} /></div>
                  <div className="flex items-center justify-between gap-2"><span className="flex min-w-0 items-center gap-2 text-sm font-medium text-ink"><span className="shrink-0">{f.away.team && teamFlag(f.away.team)}</span> <span className="truncate">{awayName}</span></span><FormChips form={preview.form.away} /></div>
                </CardBody>
              </Card>
            )}
            {preview.h2h && (
              <Card>
                <CardHeader><span className="font-display font-bold text-ink">{t.match.headToHead}</span></CardHeader>
                <CardBody>
                  <div className="mb-3 grid grid-cols-3 items-center text-center">
                    <div><div className="tnum text-2xl font-extrabold text-accent">{preview.h2h.homeWins}</div><div className="text-[11px] text-faint">{fmt(t.match.h2h.teamWins, { team: homeName })}</div></div>
                    <div><div className="tnum text-2xl font-extrabold text-muted">{preview.h2h.draws}</div><div className="text-[11px] text-faint">{fmt(t.match.h2h.drawsTotal, { games: preview.h2h.games })}</div></div>
                    <div><div className="tnum text-2xl font-extrabold text-info">{preview.h2h.awayWins}</div><div className="text-[11px] text-faint">{fmt(t.match.h2h.teamWins, { team: awayName })}</div></div>
                  </div>
                  <div className="border-t border-line pt-2">
                    <div className="mb-1 text-[11px] uppercase tracking-wide text-faint">{t.match.h2h.recentMeetings}</div>
                    <ul className="space-y-1 text-sm">
                      {preview.h2h.last.map((m, i) => (
                        <li key={i} className="flex items-center justify-between gap-2 text-ink-soft"><span className="shrink-0 text-faint">{m.date.slice(0, 10)}</span><span className="min-w-0 truncate text-right">{m.home} <span className="tnum font-semibold text-ink">{m.homeScore}–{m.awayScore}</span> {m.away}</span></li>
                      ))}
                    </ul>
                  </div>
                </CardBody>
              </Card>
            )}
          </div>
        </div>
      )}

      <p className="text-center text-xs text-faint">{preview.dataNote}</p>
    </div>
  );
}
