'use client';

import type { PublicState } from '@pintrush/engine';
import type { RoomSnapshot } from '@pintrush/protocol';
import { useEffect, useMemo, useState } from 'react';
import { LogoMark, LogoWordmark } from '@/components/brand/Logo';
import { CalendarIcon, ClockIcon, GridIcon, PhoneIcon, QrIcon, TrophyIcon } from '@/components/ui/icons';
import { cn } from '@/lib/cn';
import { formatClock, formatEventTime } from '@/lib/tv/format';
import { attractBoard, attractPanels, lastRoundPodium, type AttractPanel } from '@/lib/tv/results';
import { useTvEnv } from '../context';
import { useStageCountdown } from '../parts/Countdown';
import { JoinQr } from '../parts/JoinQr';
import { Leaderboard } from '../parts/Leaderboard';
import { Podium } from '../parts/Podium';
import s from '../tv.module.css';

const PANEL_MS = 12_000;

function NextRoundCard({ nextRoundAt, nextLabel }: { nextRoundAt: number | null; nextLabel: string | null }) {
  const ms = useStageCountdown(nextRoundAt, 250);
  const counting = nextRoundAt !== null && ms > 0;
  return (
    <div className="flex min-w-0 flex-1 flex-col gap-[10px] rounded-[28px] border border-cyan/45 bg-cyan/10 px-[32px] py-[26px]">
      <p className="flex items-center gap-[12px] text-[22px] font-bold tracking-[0.2em] text-cyan-soft uppercase">
        <ClockIcon className="size-[28px]" />
        {counting ? 'Next round in' : 'Next round'}
      </p>
      {counting ? (
        <p className="num font-display text-[96px] leading-none font-extrabold">{formatClock(ms)}</p>
      ) : (
        <p className="font-display text-[46px] leading-[1.05] font-bold">Starts when you join</p>
      )}
      {nextLabel && <p className="truncate text-[26px] font-semibold text-muted">Up next: {nextLabel}</p>}
    </div>
  );
}

function ChampionshipCard({ snapshot, pub }: { snapshot: RoomSnapshot | null; pub: PublicState | null }) {
  const { conn, timeZone } = useTvEnv();
  const next = snapshot?.attract.nextChampionship ?? null;
  // A championship that is already running is announced by its own name instead.
  if (pub?.mode === 'CHAMPIONSHIP' && snapshot?.activeEventName) {
    return (
      <div className="flex min-w-0 flex-1 flex-col gap-[10px] rounded-[28px] border border-amber/45 bg-amber/10 px-[32px] py-[26px]">
        <p className="flex items-center gap-[12px] text-[22px] font-bold tracking-[0.2em] text-amber-soft uppercase">
          <TrophyIcon className="size-[28px]" />
          Live championship
        </p>
        <p className="line-clamp-2 font-display text-[42px] leading-[1.08] font-bold">{snapshot.activeEventName}</p>
        {pub.plan && (
          <p className="text-[26px] font-semibold text-muted">
            Round {Math.min(pub.plan.index + 1, pub.plan.total)} of {pub.plan.total}
          </p>
        )}
      </div>
    );
  }
  if (!next) return null;
  const now = conn ? conn.serverNow() : snapshot?.serverNow ?? next.scheduledAt;
  return (
    <div className="flex min-w-0 flex-1 flex-col gap-[10px] rounded-[28px] border border-amber/45 bg-amber/10 px-[32px] py-[26px]">
      <p className="flex items-center gap-[12px] text-[22px] font-bold tracking-[0.2em] text-amber-soft uppercase">
        <CalendarIcon className="size-[28px]" />
        Next championship
      </p>
      <p className="font-display text-[50px] leading-none font-extrabold">{formatEventTime(next.scheduledAt, now, timeZone)}</p>
      <p className="truncate text-[26px] font-semibold text-muted">{next.name}</p>
    </div>
  );
}

function HowToPanel() {
  const steps = [
    { icon: QrIcon, title: 'Scan the code', body: 'Your phone opens the game. No app, no account, just a nickname.', tone: 'border-cyan/45 bg-cyan/10 text-cyan' },
    { icon: PhoneIcon, title: 'Answer fast', body: 'Correct answers score 100 or 150, plus up to 50 for speed.', tone: 'border-violet/50 bg-violet/15 text-violet-soft' },
    { icon: GridIcon, title: 'Light up your board', body: 'Each correct answer lights a tile. Lines +250, full board +500.', tone: 'border-amber/45 bg-amber/10 text-amber' },
  ];
  return (
    <div className="flex h-full flex-col">
      <h2 className="text-[26px] font-bold tracking-[0.2em] text-subtle uppercase">How to play</h2>
      <ol className="mt-[36px] flex flex-1 flex-col justify-around gap-[24px]">
        {steps.map(({ icon: Icon, title, body, tone }, i) => (
          <li key={title} className="flex items-start gap-[28px]">
            <span className={cn('grid size-[104px] shrink-0 place-items-center rounded-[28px] border', tone)}>
              <Icon className="size-[52px]" />
            </span>
            <div className="flex flex-col gap-[10px] pt-[6px]">
              <p className="font-display text-[38px] leading-tight font-bold">
                <span className="num mr-[14px] text-subtle">{i + 1}</span>
                {title}
              </p>
              <p className="text-[30px] leading-snug text-muted">{body}</p>
            </div>
          </li>
        ))}
      </ol>
    </div>
  );
}

/** Between rounds and whenever nobody is playing: how to join, when the next round starts, who leads. */
export function AttractScreen({ pub, snapshot }: { pub: PublicState | null; snapshot: RoomSnapshot | null }) {
  const { venueName, joinCode, joinUrlText } = useTvEnv();
  const nightlyTop = snapshot?.attract.nightlyTop;
  const board = useMemo(() => attractBoard(nightlyTop, pub), [nightlyTop, pub]);
  const { standings } = board;
  const championship = board.kind === 'championship';
  const boardTitle = championship ? 'Championship standings' : 'Tonight’s top 10';
  const lastRound = pub?.lastRound ?? null;
  const podium = lastRoundPodium(lastRound);
  const panels = attractPanels({ standings, lastRound });
  const panelKey = panels.join('|');
  const panelCount = panels.length;
  // Restart the rotation from the first panel whenever the set of available panels changes.
  const [rotation, setRotation] = useState({ key: panelKey, tick: 0 });
  if (rotation.key !== panelKey) setRotation({ key: panelKey, tick: 0 });
  useEffect(() => {
    if (panelCount < 2) return;
    const id = setInterval(() => setRotation((r) => ({ ...r, tick: r.tick + 1 })), PANEL_MS);
    return () => clearInterval(id);
  }, [panelKey, panelCount]);
  const tick = rotation.key === panelKey ? rotation.tick : 0;
  const panel: AttractPanel = panels[tick % panelCount] ?? 'howTo';
  const nextRoundAt = pub?.nextRoundAt ?? snapshot?.attract.nextRoundAt ?? null;
  const showNextRound = pub !== null && pub.status === 'RUNNING';

  return (
    <div className="absolute inset-0 grid grid-cols-[1060px_1fr] gap-[64px] px-[80px] py-[64px]">
      <div className="flex min-w-0 flex-col justify-between">
        <div className="flex items-center gap-[24px]">
          <LogoMark className="size-[88px]" />
          <div className="min-w-0">
            <LogoWordmark className="text-[52px]" />
            <p className="mt-[10px] truncate text-[30px] font-semibold text-muted">
              Live at <span className="text-fg">{venueName}</span>
            </p>
          </div>
        </div>

        <div className="flex items-center gap-[56px]">
          <JoinQr size={430} />
          <div className="flex min-w-0 flex-col gap-[22px]">
            <h1 className="font-display text-[104px] leading-[0.95] font-extrabold tracking-[-0.04em]">
              Scan
              <br />
              <span className="text-gradient-brand">to play</span>
            </h1>
            <p className="text-[36px] leading-snug text-muted">No app, no sign-up.</p>
            <div className="flex flex-col gap-[6px] text-[28px] text-subtle">
              <span>or go to</span>
              <span className="font-semibold break-all text-fg">{joinUrlText}</span>
              <span>
                code <span className="font-display text-[34px] font-bold text-amber">{joinCode}</span>
              </span>
            </div>
          </div>
        </div>

        <div className="flex gap-[28px]">
          {showNextRound ? (
            <NextRoundCard nextRoundAt={nextRoundAt} nextLabel={pub.plan?.label ?? null} />
          ) : (
            !snapshot?.attract.nextChampionship && (
              <div className="flex flex-1 flex-col gap-[10px] rounded-[28px] border border-line bg-surface/80 px-[32px] py-[26px]">
                <p className="text-[22px] font-bold tracking-[0.2em] text-subtle uppercase">Game night</p>
                <p className="font-display text-[44px] leading-[1.08] font-bold">The next game will start on this screen</p>
              </div>
            )
          )}
          <ChampionshipCard snapshot={snapshot} pub={pub} />
        </div>
      </div>

      <section aria-label="Tonight at a glance" className="relative flex min-h-0 flex-col rounded-[36px] border border-line bg-surface/85 p-[44px] shadow-card">
        <div key={`${panel}:${tick}`} className={cn('min-h-0 flex-1', s.panelIn)}>
          {panel === 'leaderboard' && (
            <div className="flex h-full flex-col">
              <div className="mb-[24px] flex items-center justify-between">
                <h2 className="text-[26px] font-bold tracking-[0.2em] text-subtle uppercase">{boardTitle}</h2>
                <TrophyIcon className="size-[40px] text-amber" />
              </div>
              <Leaderboard standings={standings} label={boardTitle} />
            </div>
          )}
          {panel === 'lastRound' && lastRound && (
            <div className="flex h-full flex-col">
              <h2 className="text-[26px] font-bold tracking-[0.2em] text-subtle uppercase">Last round</h2>
              <p className="mt-[12px] font-display text-[60px] leading-none font-extrabold">{lastRound.label}</p>
              <p className="mt-[14px] text-[28px] text-muted">Round points, top three</p>
              <Podium
                className="mt-auto"
                label={`${lastRound.label} podium`}
                entries={podium.map((p) => ({ id: p.playerId, name: p.nickname, points: p.points }))}
              />
            </div>
          )}
          {panel === 'howTo' && <HowToPanel />}
        </div>
        {panels.length > 1 && (
          <div aria-hidden="true" className="mt-[24px] flex justify-center gap-[12px]">
            {panels.map((p) => (
              <span key={p} className={cn('h-[10px] rounded-full transition-all duration-500', p === panel ? 'w-[44px] bg-cyan' : 'w-[10px] bg-line-strong')} />
            ))}
          </div>
        )}
      </section>
    </div>
  );
}
