'use client';

import type { PublicState } from '@pintrush/engine';
import type { RoomSnapshot } from '@pintrush/protocol';
import { LogoMark } from '@/components/brand/Logo';
import { ClockIcon, TrophyIcon, UsersIcon } from '@/components/ui/icons';
import { cn } from '@/lib/cn';
import { useServerNow } from '@/lib/game';
import { formatClock, formatClockTime } from '@/lib/tv/format';
import { lobbyStart, lobbyTitleFit } from '@/lib/tv/lobby';
import { tableBoards } from '@/lib/tv/results';
import { useTvEnv } from '../context';
import { cssVars } from '../cssVars';
import { PointsTicker } from '../parts/Leaderboard';
import { JoinQr } from '../parts/JoinQr';
import s from '../tv.module.css';

/**
 * Header geometry on the 1920 px stage: 1760 px of content minus the 84 px logo, its 24 px gap, the
 * 40 px column gap and the 452 px start column leaves this much for the event name.
 */
const START_COLUMN_WIDTH = 452;
const TITLE_WIDTH = 1160;

/**
 * When the show starts. A countdown and clock time (venue time zone) only within the hour; a lobby
 * opened the day before must not pulse "starting soon" next to tomorrow's date, and championships
 * start when the host presses start, so anything else says exactly that.
 */
function LobbyStartStatus({ scheduledAt }: { scheduledAt: number | null }) {
  const { conn, timeZone } = useTvEnv();
  const now = useServerNow(conn, 250);
  const start = lobbyStart(scheduledAt, now);
  if (start.kind === 'countdown') {
    const left = formatClock(start.startsAt - now);
    const at = formatClockTime(start.startsAt, timeZone);
    return (
      // Two compact rows (about as tall as a one-line title) so the tables panel keeps its four rows.
      <div role="timer" aria-label={`Starts at ${at}, in ${left}`} className="flex flex-col items-end gap-[4px] rounded-[24px] border border-lime/50 bg-lime/10 px-[28px] py-[12px] text-right">
        <p className="flex items-center gap-[10px] text-[22px] font-bold tracking-[0.2em] whitespace-nowrap text-lime uppercase">
          <ClockIcon className="size-[26px]" />
          Starts at {at}
        </p>
        <p className="num font-display text-[64px] leading-none font-extrabold">{left}</p>
      </div>
    );
  }
  if (start.kind === 'due') {
    return (
      <span className={cn('rounded-full bg-lime px-[30px] py-[12px] font-display text-[30px] font-extrabold tracking-[0.06em] text-on-bright uppercase', s.urgent)}>
        Starting any moment
      </span>
    );
  }
  return (
    <>
      <span className="rounded-full border border-lime/50 bg-lime/10 px-[30px] py-[12px] font-display text-[28px] font-extrabold tracking-[0.06em] text-lime uppercase">Lobby open</span>
      <span className="text-[26px] font-semibold text-muted">Starts when the host is ready</span>
    </>
  );
}

/** Championship lobby: get everyone in, show who just joined and which tables are forming. */
export function LobbyScreen({ pub, snapshot }: { pub: PublicState; snapshot: RoomSnapshot | null }) {
  const { joinCode, joinUrlText, venueName } = useTvEnv();
  const name = snapshot?.activeEventName ?? 'Championship';
  const title = lobbyTitleFit(name, TITLE_WIDTH);
  const boards = tableBoards(pub);
  // Nothing is scored yet, so order carries no meaning here: tables forming first, then solo players.
  const entries = boards.show ? [...boards.tables.filter((t) => !t.isSolo), ...boards.tables.filter((t) => t.isSolo)] : [];
  // A two-line title takes one row of chips from the panel below it.
  const maxEntries = title.lines === 2 ? 6 : 8;
  const hidden = Math.max(0, entries.length - maxEntries);
  const joins = pub.recentJoins;
  // A handful of names fits on one line; more scroll as a marquee, duplicated so it loops seamlessly.
  const scroll = joins.length >= 4;
  const ticker = scroll ? [...joins, ...joins] : joins;

  return (
    <div className="absolute inset-0 flex flex-col px-[80px] pt-[60px] pb-[56px]">
      <header className="flex items-center justify-between gap-[40px]">
        <div className="flex min-w-0 flex-1 items-center gap-[24px]">
          <LogoMark className="size-[84px]" />
          <div className="min-w-0">
            <p className="flex items-center gap-[12px] text-[24px] font-bold tracking-[0.22em] text-amber uppercase">
              <TrophyIcon className="size-[30px]" />
              Championship · {venueName}
            </p>
            {/*
              Sized from the name's length to fit TITLE_WIDTH in one or two lines, never truncated (a clamp
              would also clip the face's descenders). Only a 70+ character name can wrap to a third line,
              at 40 px, which is no taller than two lines at 64.
            */}
            <h1 className="mt-[8px] font-display leading-[1.04] font-extrabold tracking-[-0.03em] break-words" style={{ fontSize: title.size }}>
              {name}
            </h1>
          </div>
        </div>
        <div className="flex shrink-0 flex-col items-end gap-[10px]" style={{ width: START_COLUMN_WIDTH }}>
          <LobbyStartStatus scheduledAt={snapshot?.activeEventScheduledAt ?? null} />
        </div>
      </header>

      <div className="mt-[52px] grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)_760px] gap-[64px]">
        <div className="flex min-w-0 items-center gap-[56px]">
          <JoinQr size={460} />
          <div className="flex min-w-0 flex-col gap-[24px]">
            <h2 className="font-display text-[86px] leading-[0.98] font-extrabold tracking-[-0.04em]">
              Scan to
              <br />
              <span className="text-gradient-brand">join in</span>
            </h2>
            <p className="text-[34px] leading-snug text-muted">Pick a nickname, then set your table name to play as a team.</p>
            <p className="text-[28px] text-subtle">
              <span className="font-semibold text-fg">{joinUrlText}</span> · code <span className="font-display font-bold text-amber">{joinCode}</span>
            </p>
          </div>
        </div>

        <div className="flex min-h-0 flex-col gap-[28px]">
          <div className="flex items-end justify-between rounded-[32px] border border-violet/50 bg-violet/15 px-[40px] py-[28px] shadow-glow-violet">
            <div>
              <p className="flex items-center gap-[12px] text-[24px] font-bold tracking-[0.2em] text-violet-soft uppercase">
                <UsersIcon className="size-[30px]" />
                Players in
              </p>
              {pub.plan && (
                <p className="mt-[10px] text-[26px] text-muted">
                  {pub.plan.total} rounds{pub.plan.label ? ` · opens with ${pub.plan.label}` : ''}
                </p>
              )}
            </div>
            <PointsTicker value={pub.playerCount} className="font-display text-[150px] leading-[0.85] font-extrabold" />
          </div>

          <section aria-label={boards.title} className="flex min-h-0 flex-1 flex-col rounded-[32px] border border-line bg-surface/85 p-[32px]">
            <div className="flex items-baseline justify-between gap-[16px]">
              <h3 className="text-[22px] font-bold tracking-[0.2em] text-cyan-soft uppercase">{boards.title}</h3>
              {hidden > 0 && <p className="num shrink-0 text-[22px] font-semibold text-subtle">+{hidden} more</p>}
            </div>
            {entries.length > 0 ? (
              <ul className="mt-[18px] grid grid-cols-2 gap-[14px]">
                {entries.slice(0, maxEntries).map((t, i) => (
                  <li key={t.teamId} className={cn('flex min-w-0 items-center justify-between gap-[12px] rounded-[16px] bg-raised/60 px-[18px] py-[14px]', s.chipIn)} style={cssVars({ '--delay': `${i * 60}ms` })}>
                    <span className="min-w-0 truncate text-[28px] font-semibold">{t.name}</span>
                    {t.isSolo ? (
                      <span className="shrink-0 text-[20px] font-bold tracking-[0.14em] text-subtle uppercase">Solo</span>
                    ) : (
                      <span className="num shrink-0 rounded-full bg-cyan/15 px-[12px] py-[2px] text-[22px] font-bold text-cyan-soft">
                        <span className="sr-only">Players: </span>
                        {t.members}
                      </span>
                    )}
                  </li>
                ))}
              </ul>
            ) : (
              <p className="mt-[18px] text-[30px] leading-snug text-muted">No tables yet. Set a table name on your phone to team up with your friends.</p>
            )}
          </section>
        </div>
      </div>

      <section aria-label="Just joined" className="mt-[40px] flex h-[92px] items-center gap-[28px] overflow-hidden rounded-full border border-line bg-surface/80 pr-[12px] pl-[36px]">
        <p className="shrink-0 text-[24px] font-bold tracking-[0.2em] text-lime uppercase">Just joined</p>
        {ticker.length > 0 ? (
          <div className="mask-fade-x min-w-0 flex-1 overflow-hidden">
            <ul className={cn('flex w-max', scroll && s.ticker)} style={cssVars({ '--duration': `${Math.max(16, joins.length * 4)}s` })}>
              {ticker.map((n, i) => (
                <li key={`${n}-${i}`} aria-hidden={i >= joins.length} className="mr-[16px] shrink-0 rounded-full bg-raised px-[24px] py-[10px] text-[28px] font-semibold whitespace-nowrap">
                  {n}
                </li>
              ))}
            </ul>
          </div>
        ) : (
          <p className="text-[28px] text-muted">Be the first one in.</p>
        )}
      </section>
    </div>
  );
}
