'use client';

import { useId } from 'react';
import { useCountdown } from '@/lib/game';
import { cn } from '@/lib/cn';
import { formatClock, secondsLeft } from '@/lib/tv/format';
import { useTvEnv } from '../context';
import s from '../tv.module.css';

/** Milliseconds until a server timestamp, ticking on the shared server clock. */
export function useStageCountdown(endsAt: number | null | undefined, intervalMs = 250): number {
  const { conn } = useTvEnv();
  return useCountdown(conn, endsAt, intervalMs);
}

/** "0:42"-style clock to a server timestamp. */
export function CountdownClock({ endsAt, className }: { endsAt: number; className?: string }) {
  const ms = useStageCountdown(endsAt);
  return <span className={cn('num', className)}>{formatClock(ms)}</span>;
}

/** Plain whole seconds left ("6"). */
export function CountdownSeconds({ endsAt, className }: { endsAt: number; className?: string }) {
  const ms = useStageCountdown(endsAt);
  return <span className={cn('num', className)}>{secondsLeft(ms)}</span>;
}

/** A thin bar that drains towards a server timestamp (phase timers). */
export function DrainBar({ startsAt, endsAt, className, tone = 'cyan' }: { startsAt: number; endsAt: number; className?: string; tone?: 'cyan' | 'violet' | 'amber' }) {
  const ms = useStageCountdown(endsAt, 100);
  const span = Math.max(1, endsAt - startsAt);
  const progress = Math.min(1, Math.max(0, ms / span));
  const fill = {
    cyan: 'bg-[linear-gradient(90deg,var(--color-cyan-deep),var(--color-cyan))]',
    violet: 'bg-[linear-gradient(90deg,var(--color-violet-deep),var(--color-violet-soft))]',
    amber: 'bg-[linear-gradient(90deg,var(--color-amber),var(--color-amber-soft))]',
  }[tone];
  return (
    <div aria-hidden="true" className={cn('h-[10px] overflow-hidden rounded-full bg-line/70', className)}>
      <div className={cn('h-full origin-left rounded-full transition-transform duration-100 ease-linear', fill)} style={{ transform: `scaleX(${progress})` }} />
    </div>
  );
}

const RING_RADIUS = 44;

/**
 * The answer-window countdown ring (default 280 px, spec minimum 160 px). Turns amber for the last
 * five seconds and red for the last three, with the number always shown so colour is never the
 * only signal.
 */
export function CountdownRing({ openedAt, closesAt, size = 280 }: { openedAt: number; closesAt: number; size?: number }) {
  const ms = useStageCountdown(closesAt, 100);
  const gradientId = `tv-ring-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}`;
  const total = Math.max(1, closesAt - openedAt);
  const progress = Math.min(1, Math.max(0, ms / total));
  const seconds = secondsLeft(ms);
  const tone = seconds <= 3 ? 'danger' : seconds <= 5 ? 'amber' : 'brand';
  const stroke = tone === 'danger' ? 'var(--color-danger)' : tone === 'amber' ? 'var(--color-amber)' : `url(#${gradientId})`;
  return (
    <div
      role="timer"
      aria-label={`${seconds} seconds left`}
      className={cn('relative shrink-0', seconds <= 3 && seconds > 0 && s.urgent)}
      style={{ width: size, height: size }}
    >
      <svg viewBox="0 0 100 100" className="size-full -rotate-90" aria-hidden="true">
        <defs>
          <linearGradient id={gradientId} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="var(--color-violet-soft)" />
            <stop offset="1" stopColor="var(--color-cyan)" />
          </linearGradient>
        </defs>
        <circle cx="50" cy="50" r={RING_RADIUS + 4} fill="rgb(7 11 31 / 0.65)" />
        <circle cx="50" cy="50" r={RING_RADIUS} fill="none" stroke="var(--color-line)" strokeWidth="7" />
        <circle
          cx="50"
          cy="50"
          r={RING_RADIUS}
          fill="none"
          stroke={stroke}
          strokeWidth="7"
          strokeLinecap="round"
          pathLength={100}
          strokeDasharray="100"
          strokeDashoffset={100 - progress * 100}
          className="transition-[stroke-dashoffset] duration-100 ease-linear"
        />
      </svg>
      <span
        aria-hidden="true"
        className={cn(
          'num absolute inset-0 grid place-items-center font-display leading-none font-extrabold',
          tone === 'danger' ? 'text-danger-soft' : tone === 'amber' ? 'text-amber' : 'text-fg',
        )}
        style={{ fontSize: Math.round(size * 0.4) }}
      >
        {seconds}
      </span>
    </div>
  );
}
