import { lazy, Suspense, useMemo, useState } from 'react';
import { Link } from '@tanstack/react-router';
import { Gauge, TrendingUp, Trophy } from 'lucide-react';
import { PageHeader } from '@/components/ui/PageHeader';
import { Card, CardBody, CardHeader } from '@/components/ui/Card';
import { OddsTable } from '@/components/OddsTable';
import { PredictionList, type PredictionDay } from '@/components/PredictionList';

// Recharts is heavy and only used here — load it as a separate on-demand chunk.
const OddsChart = lazy(() => import('@/components/OddsChart').then((m) => ({ default: m.OddsChart })));
import { teamFlag } from '@/lib/teams';
import { groupByDay } from '@/lib/fixtures';
import { cn } from '@/lib/cn';
import { fmt, useFormat } from '@/lib/i18n';
import { useTournamentStore } from '@/stores/tournamentStore';

type Range = 'next3' | 'all';
type StageFilter = 'all' | 'group' | 'ko';

function Chips<T extends string>({ value, onChange, options }: {
  value: T;
  onChange: (v: T) => void;
  options: { v: T; label: string }[];
}) {
  return (
    <div className="flex overflow-hidden rounded-lg border border-line text-xs font-medium">
      {options.map((o) => (
        <button
          key={o.v}
          type="button"
          onClick={() => onChange(o.v)}
          className={cn(
            'px-3 py-1.5 transition-colors',
            o.v === value ? 'bg-accent-glow font-bold text-accent' : 'text-muted hover:bg-elevated hover:text-ink',
          )}
        >
          {o.label}
        </button>
      ))}
    </div>
  );
}

function ChampionBoard({ odds }: { odds: { team: string; champion: number }[] }) {
  const top = odds.slice(0, 8);
  const max = Math.max(...top.map((t) => t.champion), 0.01);
  return (
    <div className="space-y-2">
      {top.map((t, i) => (
        <div key={t.team} className="flex items-center gap-3">
          <span className="w-4 text-right text-xs font-bold tabular-nums text-faint">{i + 1}</span>
          <span aria-hidden className="text-lg leading-none">{teamFlag(t.team)}</span>
          <span className="w-28 shrink-0 truncate text-sm font-medium text-ink">{t.team}</span>
          <div className="h-3 flex-1 overflow-hidden rounded-full bg-elevated">
            <div
              className="h-full rounded-full bg-gradient-to-r from-accent-deep to-accent"
              style={{ width: `${(t.champion / max) * 100}%` }}
            />
          </div>
          <span className="tnum w-12 shrink-0 text-right text-sm font-bold text-ink">
            {(t.champion * 100).toFixed(1)}%
          </span>
        </div>
      ))}
    </div>
  );
}

export function PredictionsPage() {
  const { t, locale } = useFormat();
  const model = useTournamentStore((s) => s.model);
  const snapshot = useTournamentStore((s) => s.snapshot);
  const [range, setRange] = useState<Range>('next3');
  const [stage, setStage] = useState<StageFilter>('all');

  const { days, shown } = useMemo(() => {
    if (!model || !snapshot) return { days: [] as PredictionDay[], shown: 0 };
    const preds = new Map(model.matches.map((m) => [m.num, m]));
    const fixtures = snapshot.fixtures.filter(
      (f) =>
        f.status !== 'finished' &&
        preds.has(f.num) &&
        (stage === 'all' || (stage === 'group' ? f.stage === 'group' : f.stage !== 'group')),
    );
    const grouped = groupByDay(fixtures, range === 'next3' ? 3 : Infinity);
    const days = grouped.map((g) => ({
      key: g.key,
      firstKickoff: g.firstKickoff,
      items: g.fixtures.map((f) => ({ f, m: preds.get(f.num)! })),
    }));
    return { days, shown: days.reduce((s, d) => s + d.items.length, 0) };
  }, [model, snapshot, range, stage]);

  if (!model) {
    return (
      <div>
        <PageHeader title={t.predict.title} subtitle={t.predict.loadingSubtitle} />
        <div className="h-64 animate-pulse rounded-xl border border-line bg-panel" />
      </div>
    );
  }

  return (
    <div>
      <PageHeader
        title={t.predict.title}
        subtitle={fmt(t.predict.subtitle, { iterations: model.iterations.toLocaleString(locale === 'de' ? 'de-DE' : 'en-GB'), date: model.asOf })}
        actions={
          <Link to="/methodology" className="inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-sm font-medium text-muted hover:bg-elevated hover:text-ink">
            <Gauge size={15} /> {t.predict.methodologyLink}
          </Link>
        }
      />

      <div className="mb-6 grid gap-4 lg:grid-cols-2">
        <Card>
          <CardHeader className="flex items-center gap-2">
            <Trophy size={16} className="text-gold" />
            <span className="font-display font-bold text-ink">{t.predict.trophy.title}</span>
          </CardHeader>
          <CardBody>
            <ChampionBoard odds={model.odds} />
          </CardBody>
        </Card>

        <Card>
          <CardHeader className="flex items-center gap-2">
            <TrendingUp size={16} className="text-accent" />
            <span className="font-display font-bold text-ink">{t.predict.titleRace.title}</span>
          </CardHeader>
          <CardBody>
            {model.history.length >= 2 ? (
              <Suspense fallback={<div className="h-72 animate-pulse rounded-lg bg-elevated" />}>
                <OddsChart history={model.history} />
              </Suspense>
            ) : (
              <div className="grid h-72 place-items-center text-center text-sm text-muted">
                <p className="max-w-xs">{t.predict.titleRace.empty}</p>
              </div>
            )}
          </CardBody>
        </Card>
      </div>

      <h2 className="smallcaps mb-2.5">{t.predict.fullOddsHeading}</h2>
      <div className="mb-6">
        <OddsTable odds={model.odds} />
      </div>

      <div className="mb-2.5 flex flex-wrap items-center justify-between gap-2">
        <h2 className="smallcaps">{t.predict.nextMatchesHeading} <span className="tnum normal-case text-faint">({shown})</span></h2>
        <div className="flex flex-wrap gap-2">
          <Chips
            value={range}
            onChange={setRange}
            options={[
              { v: 'next3', label: t.predict.filters.next3Days },
              { v: 'all', label: t.predict.filters.allUpcoming },
            ]}
          />
          <Chips
            value={stage}
            onChange={setStage}
            options={[
              { v: 'all', label: t.predict.filters.allStages },
              { v: 'group', label: t.predict.filters.groupStage },
              { v: 'ko', label: t.predict.filters.knockout },
            ]}
          />
        </div>
      </div>
      <PredictionList days={days} />
    </div>
  );
}
