'use client';

import Link from 'next/link';
import type { ReactNode } from 'react';
import { DEFAULT_SESSION_SETTINGS, DEFAULT_TIMINGS } from '@pintrush/engine';
import { Confetti, CountdownRing, LeaderboardList, standingRows } from '@/components/game';
import { ButtonLink } from '@/components/ui/Button';
import {
  AlertIcon,
  ArrowRightIcon,
  CalendarIcon,
  CheckIcon,
  ClockIcon,
  HourglassIcon,
  MoonIcon,
  PlayIcon,
  TrophyIcon,
  UsersIcon,
  XIcon,
} from '@/components/ui/icons';
import { LogoMark } from '@/components/brand/Logo';
import { cn } from '@/lib/cn';
import { useCountdown, useServerNow } from '@/lib/game';
import { formatClock, formatPoints, formatShowTime, lobbyStartText, ordinal, plural } from '@/lib/play/format';
import { estimateNextRoundAt } from '@/lib/play/screen';
import { ActionDock, Eyebrow, ScreenBody } from '../chrome';
import { StatTile, TeamStatus, rankText } from '../parts';
import type { PlayCtx } from '../types';

function IconBadge({ tone, children }: { tone: 'cyan' | 'amber' | 'lime' | 'danger' | 'violet'; children: ReactNode }) {
  return (
    <span
      aria-hidden="true"
      className={cn(
        'grid size-20 shrink-0 place-items-center rounded-3xl border [&_svg]:size-10',
        tone === 'cyan' && 'border-cyan/50 bg-cyan/10 text-cyan shadow-glow-cyan',
        tone === 'amber' && 'border-amber/55 bg-amber/10 text-amber shadow-glow-amber',
        tone === 'lime' && 'border-lime/55 bg-lime/10 text-lime shadow-glow-lime',
        tone === 'danger' && 'border-danger/55 bg-danger/10 text-danger shadow-glow-danger',
        tone === 'violet' && 'border-violet/55 bg-violet/15 text-violet-soft shadow-glow-violet',
      )}
    >
      {children}
    </span>
  );
}

// ───────────────────────────── Connection states ─────────────────────────────

export function ConnectingScreen({ roomLabel, slow }: { roomLabel: string; slow: boolean }) {
  return (
    <ScreenBody center>
      <LogoMark className="size-20 shrink-0 motion-safe:animate-float" />
      <h1 className="mt-6 font-display text-2xl font-bold">Connecting to {roomLabel}…</h1>
      <p className="mt-2 max-w-xs text-muted" role="status">
        {slow ? 'Bar Wi-Fi being slow? We’ll keep trying — your spot is saved.' : 'Grabbing your seat at the game.'}
      </p>
      <span aria-hidden="true" className="mt-6 size-8 shrink-0 rounded-full border-4 border-line border-t-cyan motion-safe:animate-spin" />
    </ScreenBody>
  );
}

export function RemovedScreen({ joinHref, message }: { joinHref: string; message?: string }) {
  return (
    <ScreenBody center>
      <IconBadge tone="danger">
        <XIcon />
      </IconBadge>
      <h1 className="mt-6 font-display text-2xl font-bold">You’ve been removed from this game</h1>
      <p className="mt-2 max-w-xs text-muted">
        {message ?? 'The host took this nickname off the board. You can rejoin with a different, friendly name.'}
      </p>
      <ButtonLink href={joinHref} size="lg" className="mt-8 font-display">
        Back to the join screen <ArrowRightIcon />
      </ButtonLink>
    </ScreenBody>
  );
}

export function DeniedScreen({ joinHref, message }: { joinHref: string; message: string }) {
  return (
    <ScreenBody center>
      <IconBadge tone="amber">
        <AlertIcon />
      </IconBadge>
      <h1 className="mt-6 font-display text-2xl font-bold">We couldn’t open this game</h1>
      <p className="mt-2 max-w-xs text-muted">{message}</p>
      <ButtonLink href={joinHref} size="lg" className="mt-8 font-display">
        Rejoin <ArrowRightIcon />
      </ButtonLink>
    </ScreenBody>
  );
}

// ───────────────────────────── Idle / attract ─────────────────────────────

function NightlyTop({ ctx, title }: { ctx: PlayCtx; title: string }) {
  const rows = standingRows(ctx.snapshot.attract.nightlyTop, { highlightId: ctx.me?.playerId, limit: 5 });
  if (rows.length === 0) return null;
  return (
    <section className="mt-8 w-full text-left" aria-labelledby="nightly-top">
      <h2 id="nightly-top" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
        {title}
      </h2>
      <LeaderboardList rows={rows} label={title} />
    </section>
  );
}

function NextChampionshipCard({ ctx }: { ctx: PlayCtx }) {
  const next = ctx.snapshot.attract.nextChampionship;
  const now = useServerNow(ctx.conn, 30_000);
  if (!next) return null;
  return (
    <div className="mt-6 flex w-full items-center gap-3 rounded-2xl border border-amber/45 bg-amber/10 px-4 py-3 text-left">
      <CalendarIcon className="size-6 shrink-0 text-amber" />
      <div className="min-w-0">
        <p className="text-xs font-bold tracking-[0.14em] text-amber-soft uppercase">Next championship</p>
        <p className="truncate font-semibold">{next.name}</p>
        <p className="text-sm text-muted">{formatShowTime(next.scheduledAt, now)}</p>
      </div>
    </div>
  );
}

export function IdleScreen({ ctx }: { ctx: PlayCtx }) {
  const nextAt = ctx.snapshot.attract.nextRoundAt;
  const left = useCountdown(ctx.conn, nextAt, 500);
  return (
    <ScreenBody center className="justify-start pt-10">
      <IconBadge tone="violet">
        <MoonIcon />
      </IconBadge>
      <h1 className="mt-6 font-display text-2xl font-bold">No game on right now</h1>
      <p className="mt-2 max-w-xs text-muted">
        {nextAt && left > 0 ? (
          <>
            Next round in <span className="num font-bold text-fg">{formatClock(left)}</span>. Stay close!
          </>
        ) : (
          'Rounds start automatically while the bar is open. Keep this screen handy.'
        )}
      </p>
      <NextChampionshipCard ctx={ctx} />
      <NightlyTop ctx={ctx} title="Tonight’s top players" />
    </ScreenBody>
  );
}

// ───────────────────────────── Championship invite ─────────────────────────────

export function InviteScreen({ ctx }: { ctx: PlayCtx }) {
  const { snapshot, me, ctl } = ctx;
  const name = snapshot.activeEventName ?? 'The Championship';
  const lobby = ctx.championshipStage === 'lobby';
  return (
    <>
      <ScreenBody center className="justify-start pt-10">
        <IconBadge tone="amber">
          <TrophyIcon />
        </IconBadge>
        <Eyebrow tone="amber" className="mt-6">
          {lobby ? 'Lobby open' : 'Live now'}
        </Eyebrow>
        <h1 className="text-gradient-gold mt-1 font-display text-[clamp(2rem,9vw,2.75rem)] leading-tight font-extrabold">{name}</h1>
        <p className="mt-3 max-w-xs text-muted">
          {lobby
            ? 'Join now to grab your spot before the host starts. Everyone starts at zero — one tap and you’re in with the same nickname.'
            : 'The host’s show is on. Everyone starts at zero — one tap and you’re in with the same nickname.'}
        </p>
        {me && (
          <div className="mt-6 grid w-full grid-cols-2 gap-3 text-left">
            <StatTile label="You’ll play as" value={<span className="block truncate text-xl">{me.nickname}</span>} />
            <StatTile
              label="Tonight so far"
              value={me.totals.rank ? ordinal(me.totals.rank) : '—'}
              sub={`${formatPoints(me.totals.points)} pts · saved`}
            />
          </div>
        )}
      </ScreenBody>
      <ActionDock>
        <button
          type="button"
          onClick={() => void ctl.joinActive()}
          disabled={ctl.joining}
          className="flex min-h-16 w-full items-center justify-center gap-2 rounded-2xl bg-[linear-gradient(100deg,var(--color-amber),var(--color-amber-soft))] font-display text-lg font-extrabold text-on-bright shadow-glow-amber transition-transform motion-safe:active:scale-[0.98] disabled:opacity-60"
        >
          <TrophyIcon className="size-6" />
          {ctl.joining ? 'Joining…' : 'Join the Championship'}
        </button>
      </ActionDock>
    </>
  );
}

// ───────────────────────────── Championship lobby ─────────────────────────────

export function LobbyScreen({ ctx }: { ctx: PlayCtx }) {
  const { pub, me, snapshot } = ctx;
  const now = useServerNow(ctx.conn, 15_000);
  if (!pub) return null;
  const plan = pub.plan;
  // The scheduled time belongs to the room's active event, which is this lobby only when we play it.
  const startText = lobbyStartText(snapshot.mySessionActive ? snapshot.activeEventScheduledAt : null, now);
  return (
    <ScreenBody center className="justify-start pt-8">
      <span
        aria-hidden="true"
        className="grid size-20 shrink-0 place-items-center rounded-full bg-lime text-on-bright shadow-glow-lime motion-safe:animate-tile-pop"
      >
        <CheckIcon className="size-11" strokeWidth={3} />
      </span>
      <h1 className="mt-5 font-display text-[clamp(2rem,9vw,2.75rem)] leading-tight font-extrabold">You’re in!</h1>
      <p className="mt-1 text-muted">{snapshot.activeEventName ?? 'The Championship'}</p>
      <p className="mt-3 inline-flex items-center gap-2 rounded-full border border-cyan/45 bg-cyan/10 px-4 py-1.5 text-sm font-semibold text-cyan-soft">
        <ClockIcon className="size-4 shrink-0" />
        {startText}
      </p>
      {me && (
        <p className="mt-4 max-w-full truncate rounded-full border border-violet/60 bg-violet/15 px-5 py-2 font-display text-xl font-bold">
          {me.nickname}
        </p>
      )}

      <div className="mt-6 grid w-full grid-cols-2 gap-3 text-left">
        <StatTile
          label="Players"
          value={formatPoints(pub.playerCount)}
          sub={
            <span className="inline-flex items-center gap-1">
              <UsersIcon className="size-4" /> and counting
            </span>
          }
        />
        <StatTile label="The show" value={plan ? plan.total : '—'} sub={plan ? `rounds · first up: ${plan.label ?? 'The Rush'}` : 'rounds'} />
      </div>

      <TeamStatus ctx={ctx} className="mt-4 w-full text-left" />

      {pub.recentJoins.length > 0 && (
        <section className="mt-6 w-full text-left" aria-labelledby="lobby-joins">
          <h2 id="lobby-joins" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
            Just joined
          </h2>
          <ul className="flex flex-wrap gap-2">
            {pub.recentJoins.map((nick, i) => (
              <li key={`${nick}-${i}`} className="rounded-full border border-line-strong/70 bg-surface/80 px-3 py-1 text-sm font-semibold">
                {nick}
              </li>
            ))}
          </ul>
        </section>
      )}
      <p className="mt-8 flex items-center gap-2 text-sm text-muted">
        <HourglassIcon className="size-4 shrink-0 text-cyan motion-safe:animate-glow-pulse" /> Keep this screen open — your first question pops up
        here.
      </p>
    </ScreenBody>
  );
}

// ───────────────────────────── Break between rounds ─────────────────────────────

/** Ring length for the break (the countdown itself always uses the server's nextRoundAt). */
function breakLength(ctx: PlayCtx): number {
  const pub = ctx.pub;
  if (!pub || pub.mode === 'ALWAYS_ON') return DEFAULT_TIMINGS.breakMs;
  const sameSegment = pub.lastRound !== null && pub.plan?.label === pub.lastRound.label;
  return sameSegment ? DEFAULT_SESSION_SETTINGS.championshipRoundBreakMs : DEFAULT_SESSION_SETTINGS.championshipSegmentBreakMs;
}

export function BreakScreen({ ctx }: { ctx: PlayCtx }) {
  const { pub, me } = ctx;
  if (!pub) return null;
  const last = pub.lastRound;
  // Between rounds the plan cursor already points at the upcoming round, so `label` is what's next.
  const nextLabel = pub.plan?.label ?? null;
  return (
    <ScreenBody>
      <div className="flex flex-col items-center text-center">
        <Eyebrow tone="cyan">{last ? `${last.label} is done` : 'Get ready'}</Eyebrow>
        <h1 className="mt-1 font-display text-2xl font-bold">{pub.nextRoundAt ? 'Next round in' : 'Next round starting…'}</h1>
        {pub.nextRoundAt ? (
          <CountdownRing
            conn={ctx.conn}
            endsAt={pub.nextRoundAt}
            totalMs={breakLength(ctx)}
            label="Next round starts in"
            alert={false}
            className="mt-4 size-36"
          />
        ) : (
          <span aria-hidden="true" className="mt-5 size-12 shrink-0 rounded-full border-4 border-line border-t-cyan motion-safe:animate-spin" />
        )}
        {pub.mode === 'CHAMPIONSHIP' && nextLabel && <p className="mt-3 font-semibold text-violet-soft">Up next: {nextLabel}</p>}
      </div>

      {me && (
        <div className="mt-6 grid grid-cols-2 gap-3">
          <StatTile
            label="Your rank"
            value={me.totals.rank ? ordinal(me.totals.rank) : '—'}
            sub={`of ${plural(pub.playerCount, 'player')}`}
            tone="violet"
          />
          <StatTile
            label="Points"
            value={formatPoints(me.totals.points)}
            sub={`${me.totals.lines} ${me.totals.lines === 1 ? 'line' : 'lines'} tonight`}
          />
        </div>
      )}

      {last && last.podium.length > 0 && (
        <section className="mt-6" aria-labelledby="break-podium">
          <h2 id="break-podium" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
            {last.label} podium
          </h2>
          <LeaderboardList
            rows={last.podium.map((p, i) => ({
              key: p.playerId,
              rank: i + 1,
              name: p.nickname,
              score: `+${formatPoints(p.points)}`,
              highlight: p.playerId === me?.playerId,
            }))}
            label={`${last.label} podium`}
          />
        </section>
      )}

      <section className="mt-6" aria-labelledby="break-board">
        <h2 id="break-board" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
          {pub.mode === 'CHAMPIONSHIP' ? 'Championship standings' : 'Tonight’s leaderboard'}
        </h2>
        <LeaderboardList rows={standingRows(pub.leaderboard, { highlightId: me?.playerId, limit: 5 })} label="Leaderboard, top five" />
        <button
          type="button"
          onClick={() => ctx.openMenu('leaders')}
          className="mt-2 min-h-12 w-full rounded-xl text-sm font-semibold text-violet-soft hover:bg-white/[0.04]"
        >
          Full leaderboard & teams
        </button>
      </section>
    </ScreenBody>
  );
}

// ───────────────────────────── Late join: wait for the next round ─────────────────────────────

export function WaitingScreen({ ctx }: { ctx: PlayCtx }) {
  const { pub, me } = ctx;
  const nextAt = pub ? estimateNextRoundAt(pub) : null;
  const left = useCountdown(ctx.conn, nextAt, 500);
  if (!pub?.round) return null;
  const q = pub.question;
  return (
    <ScreenBody>
      <div className="flex flex-col items-center pt-4 text-center">
        <IconBadge tone="cyan">
          <HourglassIcon />
        </IconBadge>
        <h1 className="mt-5 font-display text-[clamp(1.75rem,8vw,2.25rem)] leading-tight font-extrabold">You’ll jump in next round</h1>
        <p className="mt-2 max-w-xs text-muted">
          This round was already past question 3 when you arrived. Your board is dealt the moment the next one starts.
        </p>
        {nextAt !== null && (
          <p className="mt-5 rounded-2xl border border-cyan/45 bg-cyan/10 px-5 py-3">
            <span className="block text-xs font-bold tracking-[0.14em] text-cyan-soft uppercase">Next round in about</span>
            <span className="num block font-display text-4xl font-extrabold">{formatClock(left)}</span>
          </p>
        )}
      </div>
      <p className="mt-6 flex items-center justify-center gap-2 text-sm text-muted">
        <span aria-hidden="true" className="size-2 rounded-full bg-lime motion-safe:animate-glow-pulse" />
        Now playing: {pub.round.label}
        {q ? ` · Q${q.index + 1} of ${pub.round.questionCount} · ${q.categoryLabel}` : ''}
      </p>
      <section className="mt-6" aria-labelledby="wait-board">
        <h2 id="wait-board" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
          Leaderboard
        </h2>
        <LeaderboardList rows={standingRows(pub.leaderboard, { highlightId: me?.playerId, limit: 5 })} label="Leaderboard, top five" />
      </section>
    </ScreenBody>
  );
}

// ───────────────────────────── Session complete ─────────────────────────────

/** `backOn`: tonight's always-on game is running again, so the standings come with a way back in. */
export function CompleteScreen({ ctx, backOn }: { ctx: PlayCtx; backOn: boolean }) {
  const { pub, me, embed, ctl } = ctx;
  if (!pub) return null;
  const championship = pub.mode === 'CHAMPIONSHIP';
  const champion = pub.leaderboard[0] ?? null;
  const iWon = champion !== null && champion.playerId === me?.playerId;
  const celebrate = iWon || (championship && ctx.live);
  return (
    <>
      {celebrate && (
        <div aria-hidden="true" className="pointer-events-none absolute inset-0 z-40 overflow-hidden">
          <Confetti tone={iWon ? 'gold' : 'brand'} pieces={iWon ? 64 : 40} />
        </div>
      )}
      <ScreenBody>
        <div className="flex flex-col items-center text-center">
          <Eyebrow tone="amber">{championship ? 'Final standings' : 'That’s last call'}</Eyebrow>
          <h1 className="mt-1 font-display text-[clamp(1.75rem,8vw,2.5rem)] leading-tight font-extrabold">
            {championship ? (iWon ? 'You’re the champion!' : 'The champion is crowned') : 'That’s a wrap for tonight'}
          </h1>
          {champion && (
            <div className="mt-6 w-full rounded-card border border-amber/60 bg-[linear-gradient(180deg,rgb(255_176_32/0.2),rgb(13_20_51/0.92)_70%)] p-5 shadow-glow-amber">
              <TrophyIcon className="mx-auto size-10 text-amber" />
              <p className="mt-2 text-xs font-bold tracking-[0.18em] text-amber-soft uppercase">
                {championship ? 'Champion' : 'Tonight’s top player'}
              </p>
              <p className="text-gradient-gold mt-1 truncate font-display text-3xl font-extrabold">{champion.nickname}</p>
              <p className="num mt-1 text-muted">{formatPoints(champion.points)} pts</p>
            </div>
          )}
        </div>
        {me && (
          <div className="mt-5 grid grid-cols-2 gap-3">
            <StatTile
              label="You finished"
              value={me.totals.rank ? ordinal(me.totals.rank) : '—'}
              sub={`of ${plural(pub.playerCount, 'player')}`}
              tone={iWon ? 'amber' : 'violet'}
            />
            <StatTile
              label="Points"
              value={formatPoints(me.totals.points)}
              sub={`${me.totals.correct} correct · ${me.totals.lines} ${me.totals.lines === 1 ? 'line' : 'lines'}`}
            />
          </div>
        )}
        <section className="mt-6" aria-labelledby="final-board">
          <h2 id="final-board" className="mb-2 text-xs font-bold tracking-[0.14em] text-subtle uppercase">
            Top 10
          </h2>
          <LeaderboardList rows={standingRows(pub.leaderboard, { highlightId: me?.playerId })} label="Final top ten" />
          {me && me.totals.rank !== null && me.totals.rank > 10 && <p className="mt-2 text-center text-sm text-muted">You: {rankText(me)}</p>}
        </section>
        <p className="mt-8 text-center text-sm text-muted">
          {backOn
            ? 'Thanks for playing! Tonight’s regular game is running again — jump back in with the same nickname.'
            : championship
              ? 'Thanks for playing — see you at the next championship!'
              : 'Thanks for playing! Come back tomorrow for a fresh leaderboard.'}
        </p>
        {!embed && (
          <p className="mt-2 text-center text-sm">
            <Link href="/" prefetch={false} className="inline-flex min-h-12 items-center font-semibold text-violet-soft underline-offset-4 hover:underline">
              What is PintRush?
            </Link>
          </p>
        )}
      </ScreenBody>
      {backOn && (
        <ActionDock>
          <p className="mb-2.5 flex items-center justify-center gap-2 text-sm font-semibold text-lime-soft">
            <span aria-hidden="true" className="size-2 shrink-0 rounded-full bg-lime motion-safe:animate-glow-pulse" />
            Tonight’s game is back on
          </p>
          <button
            type="button"
            onClick={() => void ctl.joinActive()}
            disabled={ctl.joining}
            className="flex min-h-16 w-full items-center justify-center gap-2 rounded-2xl bg-[linear-gradient(100deg,var(--color-violet-strong),var(--color-violet-deep))] font-display text-lg font-extrabold text-white shadow-glow-violet transition-transform motion-safe:active:scale-[0.98] disabled:opacity-60"
          >
            <PlayIcon className="size-6 shrink-0" />
            {ctl.joining ? 'Joining…' : 'Keep playing'}
          </button>
        </ActionDock>
      )}
    </>
  );
}
