'use client';

import { useCountdown, type GameConnection } from '@/lib/game';
import { cn } from '@/lib/cn';
import s from './game.module.css';

/** Urgency bands shared by bar and ring: the last 5 s go amber, the last 3 s danger. */
function urgency(remainingMs: number): 'calm' | 'warn' | 'urgent' {
  if (remainingMs <= 3_000) return 'urgent';
  if (remainingMs <= 5_000) return 'warn';
  return 'calm';
}

const secs = (ms: number) => Math.max(0, Math.ceil(ms / 1000));

export interface CountdownViewProps {
  remainingMs: number;
  /** Turn amber/red in the last seconds (answer windows). Off for calm waits like "opens in". */
  alert?: boolean;
  /** Full length of the window, for the fill fraction. */
  totalMs: number;
  /** Accessible description, e.g. "Time left to answer". */
  label: string;
  className?: string;
}

/** Horizontal timer bar with the seconds next to it. */
export function CountdownBarView({
  remainingMs,
  totalMs,
  label,
  className,
  alert = true,
  showSeconds = true,
}: CountdownViewProps & { showSeconds?: boolean }) {
  const frac = totalMs > 0 ? Math.max(0, Math.min(1, remainingMs / totalMs)) : 0;
  const u = alert ? urgency(remainingMs) : 'calm';
  return (
    <div className={cn('flex items-center gap-3', className)}>
      <div
        role="progressbar"
        aria-label={label}
        aria-valuemin={0}
        aria-valuemax={Math.round(totalMs / 1000)}
        aria-valuenow={secs(remainingMs)}
        aria-valuetext={`${secs(remainingMs)} seconds left`}
        className="h-2.5 flex-1 overflow-hidden rounded-full bg-line/80"
      >
        <div
          className={cn(
            'h-full rounded-full',
            s.barFill,
            u === 'calm' && 'bg-[linear-gradient(90deg,var(--color-cyan),var(--color-violet))]',
            u === 'warn' && 'bg-amber',
            u === 'urgent' && cn('bg-danger', s.urgent),
          )}
          style={{ width: `${frac * 100}%` }}
        />
      </div>
      {showSeconds && (
        <span
          aria-hidden="true"
          className={cn(
            'num w-[2.5ch] text-right font-display text-xl font-bold',
            u === 'calm' ? 'text-fg' : u === 'warn' ? 'text-amber' : 'text-danger-soft',
          )}
        >
          {secs(remainingMs)}
        </span>
      )}
    </div>
  );
}

/** Circular countdown with the seconds in the middle. Size it with className (e.g. `size-16`, TV `size-48`). */
export function CountdownRingView({ remainingMs, totalMs, label, className, alert = true }: CountdownViewProps) {
  const frac = totalMs > 0 ? Math.max(0, Math.min(1, remainingMs / totalMs)) : 0;
  const u = alert ? urgency(remainingMs) : 'calm';
  const stroke = u === 'calm' ? 'var(--color-cyan)' : u === 'warn' ? 'var(--color-amber)' : 'var(--color-danger)';
  return (
    <div role="timer" aria-label={`${label}: ${secs(remainingMs)} seconds`} className={cn('@container relative aspect-square shrink-0', className)}>
      <svg viewBox="0 0 40 40" className="size-full -rotate-90" aria-hidden="true">
        <circle cx="20" cy="20" r="17" fill="none" stroke="var(--color-line)" strokeWidth="3.4" />
        <circle
          cx="20"
          cy="20"
          r="17"
          fill="none"
          stroke={stroke}
          strokeWidth="3.4"
          strokeLinecap="round"
          pathLength={100}
          strokeDasharray={100}
          strokeDashoffset={100 - frac * 100}
          className="motion-safe:transition-[stroke-dashoffset] motion-safe:duration-150 motion-safe:ease-linear"
        />
      </svg>
      <span aria-hidden="true" className="num absolute inset-0 grid place-items-center font-display text-[42cqw] leading-none font-bold">
        {secs(remainingMs)}
      </span>
    </div>
  );
}

interface LiveCountdownProps {
  conn: GameConnection | null;
  /** Server epoch ms the window ends. */
  endsAt: number | null | undefined;
  totalMs: number;
  label: string;
  alert?: boolean;
  className?: string;
}

/** CountdownBarView driven by server time (useCountdown), so every phone and the TV agree. */
export function CountdownBar({ conn, endsAt, ...rest }: LiveCountdownProps & { showSeconds?: boolean }) {
  const remainingMs = useCountdown(conn, endsAt);
  return <CountdownBarView remainingMs={remainingMs} {...rest} />;
}

/** CountdownRingView driven by server time. */
export function CountdownRing({ conn, endsAt, ...rest }: LiveCountdownProps) {
  const remainingMs = useCountdown(conn, endsAt);
  return <CountdownRingView remainingMs={remainingMs} {...rest} />;
}
