'use client';

import type { ReactNode } from 'react';
import type { PowerUpType, PrivateState, PublicState } from '@pintrush/engine';
import { Board, POWER_UP_INFO, openPositions, toggleSelection, type BoardProps } from '@/components/game';
import { DoubleDownIcon, UsersIcon } from '@/components/ui/icons';
import { cn } from '@/lib/cn';
import { formatPoints, formatScore, ordinal } from '@/lib/play/format';
import type { PlayCtx } from './types';

export const LETTERS = ['A', 'B', 'C', 'D', 'E', 'F'] as const;
export const letterFor = (index: number) => LETTERS[index] ?? String(index + 1);

// Short enough to fit two buttons side by side on a 360 px phone.
const SHORT: Record<PowerUpType, string> = {
  DOUBLE_DOWN: '+200 or −100, next Q',
  SECOND_CHANCE: 'Remove a wrong answer',
  CATEGORY_SWAP: 'Swap 2 unlit squares',
};

export function PowerButton({
  type,
  onClick,
  busy,
  disabled,
  className,
}: {
  type: PowerUpType;
  onClick: () => void;
  busy?: boolean;
  disabled?: boolean;
  className?: string;
}) {
  const info = POWER_UP_INFO[type];
  const Icon = info.icon;
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled || busy}
      className={cn(
        'flex min-h-14 w-full items-center gap-2 rounded-2xl border-2 border-violet/70 bg-violet/15 px-2.5 py-2 text-left',
        'transition-[transform,background-color] duration-150 hover:bg-violet/25 motion-safe:active:scale-[0.98] disabled:opacity-50',
        className,
      )}
    >
      <Icon className="size-5 shrink-0 text-cyan" />
      <span className="min-w-0">
        <span className="block text-sm leading-tight font-semibold">{busy ? 'Activating…' : info.name}</span>
        <span className="block text-[0.6875rem] leading-tight text-muted">{SHORT[type]}</span>
      </span>
    </button>
  );
}

/** Board props that put the player's board into Category Swap selection while a swap is being picked. */
export function swapSelection(ctx: PlayCtx): Pick<BoardProps, 'selectable' | 'selected' | 'onSelect'> {
  const { ctl, me } = ctx;
  if (!ctl.swap || !me?.board) return {};
  const swap = ctl.swap;
  return { selectable: openPositions(me.board.tiles), selected: swap, onSelect: (p) => ctl.setSwap(toggleSelection(swap, p)) };
}

/**
 * Double Down / Category Swap between questions (INTRO, PENDING, REVEALED). Shows only what the
 * server lists in `me.powerUps.available`, plus the armed Double Down state.
 */
export function PowerUpDock({ ctx }: { ctx: PlayCtx }) {
  const { me, ctl } = ctx;
  if (!me || !me.powerUps.enabled) return null;
  const available = me.powerUps.available;
  const canDoubleDown = available.includes('DOUBLE_DOWN');
  const canSwap = available.includes('CATEGORY_SWAP') && me.board !== null;
  const armed = me.powerUps.doubleDownOn !== null;

  if (ctl.swap && me.board) {
    const labels = me.board.categoryLabels;
    const names = ctl.swap.map((p) => labels[me.board!.tiles[p]?.category ?? ''] ?? '?');
    return (
      <div className="flex flex-col gap-2.5">
        <p className="text-center text-sm font-semibold text-amber-soft" aria-live="polite">
          {ctl.swap.length < 2 ? `Tap two unlit squares to swap (${ctl.swap.length}/2)` : `Swap ${names[0]} ↔ ${names[1]}?`}
        </p>
        <div className="grid grid-cols-2 gap-2">
          <button
            type="button"
            onClick={() => ctl.setSwap(null)}
            className="min-h-14 rounded-2xl border-2 border-line-strong bg-raised font-semibold hover:border-violet-soft"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={() => void ctl.confirmSwap()}
            disabled={ctl.swap.length !== 2 || ctl.powerBusy !== null}
            className="min-h-14 rounded-2xl bg-amber font-display font-bold text-on-bright shadow-glow-amber disabled:opacity-50 disabled:shadow-none"
          >
            {ctl.powerBusy === 'CATEGORY_SWAP' ? 'Swapping…' : 'Swap squares'}
          </button>
        </div>
      </div>
    );
  }

  if (!canDoubleDown && !canSwap && !armed) return null;
  return (
    <div className="flex flex-col gap-2">
      {armed && (
        <p className="flex items-center justify-center gap-2 rounded-xl border border-amber/50 bg-amber/10 px-3 py-2 text-sm font-semibold text-amber-soft">
          <DoubleDownIcon className="size-5 shrink-0" /> Double Down armed: +200 if right, −100 if not
        </p>
      )}
      {(canDoubleDown || canSwap) && (
        <div className={cn('grid gap-2', canDoubleDown && canSwap ? 'grid-cols-2' : 'grid-cols-1')}>
          {canDoubleDown && <PowerButton type="DOUBLE_DOWN" onClick={() => void ctl.doubleDown()} busy={ctl.powerBusy === 'DOUBLE_DOWN'} />}
          {canSwap && <PowerButton type="CATEGORY_SWAP" onClick={() => ctl.setSwap([])} disabled={ctl.powerBusy !== null} />}
        </div>
      )}
    </div>
  );
}

export function hasPowerUpDock(me: PrivateState | null, swapping: boolean): boolean {
  if (!me || !me.powerUps.enabled) return false;
  if (swapping) return true;
  const a = me.powerUps.available;
  return a.includes('DOUBLE_DOWN') || (a.includes('CATEGORY_SWAP') && me.board !== null) || me.powerUps.doubleDownOn !== null;
}

export function StatTile({
  label,
  value,
  sub,
  tone = 'default',
}: {
  label: string;
  value: ReactNode;
  sub?: ReactNode;
  tone?: 'default' | 'amber' | 'lime' | 'violet';
}) {
  return (
    <div
      className={cn(
        'rounded-2xl border px-4 py-3',
        tone === 'default' && 'border-line bg-surface/80',
        tone === 'amber' && 'border-amber/50 bg-amber/10',
        tone === 'lime' && 'border-lime/45 bg-lime/10',
        tone === 'violet' && 'border-violet/55 bg-violet/15',
      )}
    >
      <p className="text-xs font-bold tracking-[0.14em] text-subtle uppercase">{label}</p>
      <p className="num mt-1 font-display text-2xl leading-tight font-bold">{value}</p>
      {sub && <p className="mt-0.5 text-sm text-muted">{sub}</p>}
    </div>
  );
}

/** "3rd · 2,310 pts" for the player, or a dash before they score. */
export function rankText(me: PrivateState | null): string {
  if (!me) return '—';
  const rank = me.totals.rank;
  return rank ? `${ordinal(rank)} · ${formatPoints(me.totals.points)} pts` : `${formatPoints(me.totals.points)} pts`;
}

/** Table status for team rounds and the lobby: your table and its rank, or a nudge to add one. */
export function TeamStatus({ ctx, className }: { ctx: PlayCtx; className?: string }) {
  const { me, pub, openMenu } = ctx;
  if (!me || !pub) return null;
  const team = me.teamId ? [...pub.teamLeaderboard, ...(pub.soloLeaderboard ?? [])].find((t) => t.teamId === me.teamId) : undefined;
  if (me.teamName) {
    const ranked = team && !team.isSolo;
    return (
      <div className={cn('flex items-center gap-3 rounded-2xl border border-cyan/40 bg-cyan/10 px-4 py-3', className)}>
        <UsersIcon className="size-6 shrink-0 text-cyan" />
        <div className="min-w-0 flex-1">
          <p className="text-xs font-bold tracking-[0.14em] text-cyan-soft uppercase">Your table</p>
          <p className="truncate font-display text-lg font-bold">{me.teamName}</p>
          <p className="text-sm text-muted">
            {ranked
              ? `${ordinal(team.rank)} of ${pub.teamLeaderboard.length} tables · ${formatScore(team.score)} avg`
              : 'Just you so far — tablemates join by typing the same team name.'}
          </p>
        </div>
      </div>
    );
  }
  return (
    <div className={cn('flex flex-col gap-3 rounded-2xl border border-line bg-surface/80 px-4 py-3', className)}>
      <div className="flex items-center gap-3">
        <UsersIcon className="size-6 shrink-0 text-muted" />
        <div className="min-w-0 flex-1">
          <p className="font-semibold">You’re playing solo</p>
          <p className="text-sm text-muted">Table challenges are for teams of two or more.</p>
        </div>
      </div>
      <button
        type="button"
        onClick={() => openMenu('teams')}
        className="min-h-12 rounded-xl border-2 border-cyan/60 bg-cyan/10 font-semibold text-cyan-soft hover:bg-cyan/20"
      >
        Add your table
      </button>
    </div>
  );
}

/** Lobby/break helper: the next plan item label for championships. */
export function nextUp(pub: PublicState): string | null {
  return pub.plan?.nextLabel ?? null;
}

/** Fallback body for split-second gaps (e.g. a late joiner whose board is being dealt). */
export function Holding({ title, children }: { title: string; children?: ReactNode }) {
  return (
    <div className="flex flex-col items-center gap-3 py-10 text-center" role="status">
      <span aria-hidden="true" className="size-10 shrink-0 rounded-full border-4 border-line border-t-cyan motion-safe:animate-spin" />
      <p className="font-display text-xl font-bold">{title}</p>
      {children && <div className="max-w-xs text-sm text-muted">{children}</div>}
    </div>
  );
}

/** The player's board, or nothing outside board rounds. */
export function MyBoard({ ctx, ...props }: { ctx: PlayCtx } & Omit<BoardProps, 'tiles' | 'categoryLabels' | 'lines' | 'label'> & { label?: string }) {
  const board = ctx.me?.board;
  if (!board) return null;
  return (
    <Board
      tiles={board.tiles}
      categoryLabels={board.categoryLabels}
      lines={board.lines}
      label={
        props.label ??
        `Your board: ${board.tiles.filter((t) => t.activated).length} of 9 squares lit, ${board.lines.length} ${board.lines.length === 1 ? 'line' : 'lines'}`
      }
      {...props}
    />
  );
}
