import { useEffect, useMemo, useState } from 'react';
import { Link, useParams } from '@tanstack/react-router';
import { ArrowLeft, ArrowRightLeft, CircleDot, Shield, Shirt, Volleyball } from 'lucide-react';
import { Card, CardBody, CardHeader } from '@/components/ui/Card';
import { WinProbBar } from '@/components/WinProbBar';
import { WinProbTimeline, type TimelinePoint } from '@/components/WinProbTimeline';
import { OddsMovement } from '@/components/OddsMovement';
import { FormChips } from '@/components/FormChips';
import { teamFlag } from '@/lib/teams';
import { fmt, useFormat, useT } from '@/lib/i18n';
import { inPlayProbs } from '@/lib/model/inplay';
import { useTournamentStore } from '@/stores/tournamentStore';
import type { Fixture, KeyPlayer, MatchPreview, OddsPoint } from '@/lib/types';

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

/** Crisp event markers instead of emoji: ball icon for goals, card-shaped
 *  color chips for bookings, arrows for substitutions. */
function EventIcon({ type }: { type: string }) {
  const t = type.toLowerCase();
  if (t.includes('goal') || t.includes('penalty - scored')) return <Volleyball size={14} className="shrink-0 text-accent" />;
  if (t.includes('yellow')) return <span className="inline-block h-3.5 w-2.5 shrink-0 rounded-[2px] bg-amber-400" />;
  if (t.includes('red')) return <span className="inline-block h-3.5 w-2.5 shrink-0 rounded-[2px] bg-red-500" />;
  if (t.includes('substitution')) return <ArrowRightLeft size={13} className="shrink-0 text-muted" />;
  return <CircleDot size={10} className="shrink-0 text-faint" />;
}

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">
              <span className="truncate text-ink-soft">{p.name}</span>
              <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>
            <span className="truncate">{p.name}</span>
            <span className="ml-auto text-[11px] text-faint">{p.position}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}

export function MatchPreviewPage() {
  const { num: numParam } = useParams({ strict: false }) as { num: string };
  const { t, kickoffDay, kickoffTime } = useFormat();
  const [preview, setPreview] = useState<MatchPreview | null>(null);
  const [timeline, setTimeline] = useState<TimelinePoint[]>([]);
  const [oddsHistory, setOddsHistory] = useState<OddsPoint[]>([]);
  const [failed, setFailed] = useState(false);

  // 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([]);
    setFailed(false);
    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(() => {});
    void load();
    void loadTimeline();
    // line history changes on a 3h sweep — once per visit is plenty
    fetch(`/api/odds/${numParam}`)
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then((d: { history: OddsPoint[] }) => alive && setOddsHistory(d.history))
      .catch(() => {});
    const id = setInterval(() => {
      if (useTournamentStore.getState().snapshot?.fixtures.find((f) => f.num === Number(numParam))?.status === 'live') {
        void load();
        void loadTimeline();
      }
    }, 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;
    return inPlayProbs(preview.prediction.lambdaHome, preview.prediction.lambdaAway, f.minute ?? 0, f.homeScore, f.awayScore);
  }, [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]);

  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-xl 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';
  const koT = new Date(f.kickoff).getTime();
  const hasOddsChart = oddsHistory.filter((o) => o.home_ml != null && o.draw_ml != null && o.away_ml != null && o.captured_at <= koT).length >= 2;

  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 */}
      <Card className={isLive ? 'border-live/40 ring-1 ring-live/30' : ''}>
        <CardBody>
          <div className="mb-3 text-center text-xs uppercase tracking-wide text-faint">
            {f.group ? fmt(t.common.group, { group: f.group }) : t.stage[f.stage]} · {kickoffDay(f.kickoff)} · {kickoffTime(f.kickoff)} · {preview.venue}
          </div>
          <div className="grid grid-cols-[1fr_auto_1fr] items-center gap-3">
            <Link to="/team/$name" params={{ name: f.home.team ?? '' }} className="flex flex-col items-center gap-1 hover:opacity-80">
              <span aria-hidden className="grid h-10 place-items-center text-4xl">{f.home.team ? teamFlag(f.home.team) : <Shield size={32} className="text-faint" />}</span>
              <span className="text-center text-sm font-semibold text-ink">{homeName}</span>
            </Link>
            <div className="text-center">
              {hasScore ? <div className="tnum text-3xl font-extrabold text-ink">{f.homeScore ?? 0}–{f.awayScore ?? 0}</div> : <div className="tnum text-lg font-bold text-muted">{kickoffTime(f.kickoff)}</div>}
              {isLive && <div className="inline-flex items-center gap-1 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="text-[11px] font-bold uppercase text-faint">{t.common.fullTime}</div>}
            </div>
            <Link to="/team/$name" params={{ name: f.away.team ?? '' }} className="flex flex-col items-center gap-1 hover:opacity-80">
              <span aria-hidden className="grid h-10 place-items-center text-4xl">{f.away.team ? teamFlag(f.away.team) : <Shield size={32} className="text-faint" />}</span>
              <span className="text-center text-sm font-semibold text-ink">{awayName}</span>
            </Link>
          </div>
        </CardBody>
      </Card>

      {/* LIVE: in-play win probability */}
      {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>
      )}

      {/* FT: how the win probability swung over the match */}
      {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>
      )}

      {/* LIVE/FT: stats */}
      {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>
      )}

      {/* LIVE/FT: timeline */}
      {preview.events.length > 0 && (
        <Card>
          <CardHeader><span className="font-display font-bold text-ink">{t.match.timeline}</span></CardHeader>
          <CardBody>
            <ul className="space-y-1.5">
              {preview.events.map((e, i) => (
                <li key={i} className={`flex items-center gap-2 text-sm ${e.team === 'away' ? 'flex-row-reverse text-right' : ''}`}>
                  <span className="tnum w-8 shrink-0 text-xs text-faint">{e.minute != null ? fmt(t.live.minute, { n: e.minute }) : ''}</span>
                  <span aria-hidden className="grid w-4 shrink-0 place-items-center"><EventIcon type={e.type} /></span>
                  <span className="truncate text-ink-soft">{e.text || e.type}</span>
                </li>
              ))}
            </ul>
          </CardBody>
        </Card>
      )}

      {/* model expectation */}
      {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">{fmt(t.match.expectedGoalsLine, { home: preview.prediction.lambdaHome.toFixed(2), away: preview.prediction.lambdaAway.toFixed(2) })}</p>
          </CardBody>
        </Card>
      )}

      {/* bookmaker line movement vs the model (benchmark only) */}
      {preview.prediction && hasOddsChart && (
        <Card>
          <CardHeader><span className="font-display font-bold text-ink">{t.match.oddsMovement}</span></CardHeader>
          <CardBody>
            <OddsMovement history={oddsHistory} model={preview.prediction.probs} kickoff={f.kickoff} />
          </CardBody>
        </Card>
      )}

      {/* form */}
      {(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"><span className="flex items-center gap-2 text-sm font-medium text-ink">{f.home.team && teamFlag(f.home.team)} {homeName}</span><FormChips form={preview.form.home} /></div>
            <div className="flex items-center justify-between"><span className="flex items-center gap-2 text-sm font-medium text-ink">{f.away.team && teamFlag(f.away.team)} {awayName}</span><FormChips form={preview.form.away} /></div>
          </CardBody>
        </Card>
      )}

      {/* head to head */}
      {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 text-ink-soft"><span className="text-faint">{m.date.slice(0, 10)}</span><span>{m.home} <span className="tnum font-semibold text-ink">{m.homeScore}–{m.awayScore}</span> {m.away}</span></li>
                ))}
              </ul>
            </div>
          </CardBody>
        </Card>
      )}

      {/* lineups or key players */}
      <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-2 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>

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