'use client';

import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
import { useTournament } from '@/hooks/useTournament';
import { useAlarm } from '@/hooks/useAlarm';
import TournamentDisplay from '@/components/TournamentDisplay';
import LiveQRCode from '@/components/LiveQRCode';
import {
  getBlindLevelForState,
  formatBlinds,
  getStructureLevels,
} from '@/lib/blind-structure';
import { formatCurrency } from '@/lib/prize-pool';
import {
  getDisplayPrizePool,
  getDisplayPayouts,
  formatTime,
  getRemainingSeconds,
  formatNewBlindsAnnouncement,
} from '@/lib/tournament-engine';
import {
  toSpotifyEmbedUrl,
  spotifyHistoryLabel,
  pushSpotifyHistory,
} from '@/lib/spotify';
import {
  createSpotifyController,
  type SpotifyEmbedController,
} from '@/lib/spotify-embed';
import Link from 'next/link';
import { BlindLevel } from '@/lib/types';

export default function TipPage() {
  // Poll less often — wall clock drives display accuracy
  const { tournament, loading, updateTournament } = useTournament(2000);
  const [settings, setSettings] = useState({
    speechEnabled: true,
    alarmEnabled: true,
    warningMinutes: 1,
    spotifyPlaylistHistory: [] as string[],
  });
  const prevStatusRef = useRef<string | null>(null);
  const prevLevelRef = useRef<number | null>(null);
  const announcedIndexRef = useRef<number | null>(null);
  const shuffleSpokenForId = useRef<string | null>(null);
  const advancingRef = useRef(false);
  const spotifyHostRef = useRef<HTMLDivElement | null>(null);
  const spotifyControllerRef = useRef<SpotifyEmbedController | null>(null);
  const musicDuckedRef = useRef(false);
  const editingTimeRef = useRef(false);

  const [customAnnounce, setCustomAnnounce] = useState('');
  const [editMinutes, setEditMinutes] = useState('');
  const [editSeconds, setEditSeconds] = useState('');
  const [spotifyInput, setSpotifyInput] = useState('');
  const [spotifyEmbed, setSpotifyEmbed] = useState<string | null>(null);
  const [musicMutedForSpeech, setMusicMutedForSpeech] = useState(false);
  const [audioReady, setAudioReady] = useState(false);
  const [lastSpoken, setLastSpoken] = useState<string | null>(null);
  const [displayRemaining, setDisplayRemaining] = useState(0);
  const [bountyCollectorId, setBountyCollectorId] = useState('');

  /**
   * Spotify embed cannot change volume from the parent (browser cross-origin).
   * Best we can do: pause during speech, resume after — without killing the iframe.
   */
  const duckMusic = useCallback(() => {
    const ctrl = spotifyControllerRef.current;
    if (!ctrl) return;
    try {
      ctrl.pause();
      musicDuckedRef.current = true;
      setMusicMutedForSpeech(true);
    } catch {
      /* ignore */
    }
  }, []);

  const restoreMusic = useCallback(() => {
    if (!musicDuckedRef.current) return;
    const ctrl = spotifyControllerRef.current;
    try {
      if (ctrl) {
        // resume keeps position; play() is fallback
        try {
          ctrl.resume();
        } catch {
          ctrl.play();
        }
      }
    } catch {
      /* ignore */
    }
    musicDuckedRef.current = false;
    setMusicMutedForSpeech(false);
  }, []);

  const {
    unlockAudio,
    triggerLevelEndWithAnnouncement,
    triggerWarning,
    triggerBreakAlarm,
    triggerBreakEnding,
    triggerAnnouncement,
    triggerShuffleUpAndDeal,
    resetWarning,
  } = useAlarm(settings.speechEnabled || settings.alarmEnabled, settings.warningMinutes, {
    onSpeakStart: duckMusic,
    onSpeakEnd: () => {
      // Short buffer so the last word is clear, then resume Spotify
      setTimeout(restoreMusic, 400);
    },
  });

  // Mount Spotify Embed controller (pause/resume capable — no volume API available)
  useEffect(() => {
    if (!spotifyEmbed || !spotifyHostRef.current) return;
    let cancelled = false;
    const host = spotifyHostRef.current;
    host.innerHTML = '';
    const el = document.createElement('div');
    el.style.width = '100%';
    el.style.height = '152px';
    host.appendChild(el);

    createSpotifyController(el, spotifyEmbed)
      .then((ctrl) => {
        if (cancelled) {
          try {
            ctrl.destroy();
          } catch {
            /* ignore */
          }
          return;
        }
        spotifyControllerRef.current = ctrl;
      })
      .catch(() => {
        // Fallback: plain iframe if Embed API fails
        if (cancelled || !host) return;
        host.innerHTML = '';
        const iframe = document.createElement('iframe');
        iframe.title = 'Spotify';
        iframe.src = spotifyEmbed;
        iframe.className = 'w-full rounded-lg border border-white/10';
        iframe.height = '152';
        iframe.allow =
          'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture';
        host.appendChild(iframe);
      });

    return () => {
      cancelled = true;
      try {
        spotifyControllerRef.current?.destroy();
      } catch {
        /* ignore */
      }
      spotifyControllerRef.current = null;
    };
  }, [spotifyEmbed]);

  const speakNow = useCallback(
    (text: string, label?: string) => {
      unlockAudio();
      setAudioReady(true);
      const ok = triggerAnnouncement(text);
      setLastSpoken(label || text);
      if (!ok) {
        setLastSpoken(`(speech failed — click yellow bar / check browser sound) ${text}`);
      }
      return ok;
    },
    [unlockAudio, triggerAnnouncement]
  );

  useEffect(() => {
    fetch('/api/settings')
      .then((r) => r.json())
      .then((s) =>
        setSettings({
          speechEnabled: s.speechEnabled ?? true,
          alarmEnabled: s.alarmEnabled ?? true,
          warningMinutes: s.warningMinutes ?? 1,
          spotifyPlaylistHistory: s.spotifyPlaylistHistory || [],
        })
      )
      .catch(() => {});
  }, []);

  // Unlock audio on first user interaction anywhere on TIP
  useEffect(() => {
    const unlock = () => {
      unlockAudio();
      setAudioReady(true);
    };
    window.addEventListener('pointerdown', unlock, { once: true, capture: true });
    window.addEventListener('keydown', unlock, { once: true, capture: true });
    return () => {
      window.removeEventListener('pointerdown', unlock, true);
      window.removeEventListener('keydown', unlock, true);
    };
  }, [unlockAudio]);

  const structureAnnouncements = useMemo(() => {
    if (!tournament) return [] as { index: number; n: number; text: string; level: BlindLevel }[];
    const structure = getStructureLevels(tournament.config);
    const out: { index: number; n: number; text: string; level: BlindLevel }[] = [];
    let n = 0;
    structure.forEach((level, index) => {
      if (level.isAnnouncement) {
        n += 1;
        out.push({
          index,
          n,
          text: (level.announcementText || '').trim() || `Announcement ${n}`,
          level,
        });
      }
    });
    return out;
  }, [tournament]);

  // Wall-clock display — independent of network tick speed
  useEffect(() => {
    if (!tournament) {
      setDisplayRemaining(0);
      return;
    }
    const update = () => {
      setDisplayRemaining(getRemainingSeconds(tournament));
    };
    update();
    const id = setInterval(update, 200);
    return () => clearInterval(id);
  }, [tournament]);

  // When wall clock hits 0, advance once via server (accurate wall time)
  useEffect(() => {
    if (!tournament) return;
    const active =
      tournament.status === 'running' ||
      tournament.status === 'announcement' ||
      tournament.status === 'break';
    if (!active) return;
    if (displayRemaining > 0) return;
    if (advancingRef.current) return;
    advancingRef.current = true;
    updateTournament('tick')
      .catch(() => null)
      .finally(() => {
        setTimeout(() => {
          advancingRef.current = false;
        }, 500);
      });
  }, [displayRemaining, tournament, updateTournament]);

  // Only seed edit fields when entering pause (not on every poll while typing)
  useEffect(() => {
    if (!tournament) return;
    if (tournament.status !== 'paused' && tournament.status !== 'break') {
      editingTimeRef.current = false;
      return;
    }
    if (editingTimeRef.current) return;
    const rem = getRemainingSeconds(tournament);
    setEditMinutes(String(Math.floor(rem / 60)));
    setEditSeconds(String(rem % 60).padStart(2, '0'));
  }, [tournament?.status, tournament?.currentLevel, tournament]);

  const markShuffleSpoken = useCallback((id: string) => {
    shuffleSpokenForId.current = id;
    try {
      sessionStorage.setItem(`pokerforge_shuffle_${id}`, '1');
    } catch {
      /* ignore */
    }
  }, []);

  const handleEnableAudio = useCallback(() => {
    unlockAudio();
    setAudioReady(true);
    setLastSpoken('Audio ready — you can start the tournament.');
  }, [unlockAudio]);

  /** Registration → start clock + announce (same click unlocks browser speech). */
  const handleStartTournament = useCallback(async () => {
    if (!tournament) return;
    unlockAudio();
    setAudioReady(true);
    try {
      await updateTournament('begin');
      const msg = 'Shuffle up and deal.';
      setLastSpoken(msg);
      markShuffleSpoken(tournament.id);
      // Speak on this click so the browser allows it
      triggerShuffleUpAndDeal();
    } catch {
      setLastSpoken('Could not start tournament. Try again.');
    }
  }, [tournament, unlockAudio, updateTournament, markShuffleSpoken, triggerShuffleUpAndDeal]);

  const handleBountyCollected = useCallback(async () => {
    if (!tournament || !bountyCollectorId) {
      setLastSpoken('Select who collected the bounty first.');
      return;
    }
    const collector = tournament.entries.find((e) => e.id === bountyCollectorId);
    if (!collector) return;
    unlockAudio();
    setAudioReady(true);
    try {
      await updateTournament('collect_bounty', { collectorEntryId: bountyCollectorId });
      const name = collector.playerName;
      const msg = `The bounty has been collected by ${name}. Congratulations ${name}. Now go get em.`;
      setLastSpoken(msg);
      speakNow(msg);
    } catch {
      setLastSpoken('Could not record bounty collection.');
    }
  }, [tournament, bountyCollectorId, unlockAudio, updateTournament, speakNow]);

  // Level / status transitions → speech
  // IMPORTANT: break enter/exit never use the air-raid siren.
  // Returning from break also must NOT fire level-up siren (that was the bug).
  useEffect(() => {
    if (!tournament) return;

    const level = getBlindLevelForState(tournament);
    const prevStatus = prevStatusRef.current;
    const prevLevel = prevLevelRef.current;
    const levelChanged = prevLevel !== null && prevLevel !== tournament.currentLevel;
    const comingFromBreak = prevStatus === 'break';
    const enteringBreak = prevStatus !== null && prevStatus !== 'break' && tournament.status === 'break';
    const leavingBreak =
      comingFromBreak &&
      tournament.status !== 'break' &&
      (tournament.status === 'running' || tournament.status === 'announcement');

    // 1-minute warning — wall-clock remaining, no next-blind details
    if (tournament.status === 'running' && !level.isBreak && !level.isAnnouncement) {
      triggerWarning(displayRemaining);
    }

    // Enter break — speech only, never siren
    if (enteringBreak) {
      setLastSpoken(
        `Tournament on break — ${formatTime(displayRemaining)} until resume`
      );
      if (audioReady) triggerBreakAlarm();
      resetWarning();
    }

    // Leave break — speech only, never siren
    if (leavingBreak) {
      const msg = 'Break is over. Shuffle up and deal.';
      setLastSpoken(msg);
      if (audioReady) triggerBreakEnding();
      resetWarning();
    }

    // New blind level: siren + announce ONLY when advancing play levels.
    // Skip entirely when entering/leaving break (even if level index changes).
    if (
      levelChanged &&
      !enteringBreak &&
      !leavingBreak &&
      !comingFromBreak &&
      tournament.status === 'running' &&
      !level.isBreak &&
      !level.isAnnouncement
    ) {
      resetWarning();
      const msg = formatNewBlindsAnnouncement(level);
      setLastSpoken(msg || 'Blinds up');
      if (audioReady) triggerLevelEndWithAnnouncement(msg || '');
    } else if (
      levelChanged &&
      !enteringBreak &&
      !leavingBreak &&
      level.isAnnouncement &&
      announcedIndexRef.current !== tournament.currentLevel
    ) {
      resetWarning();
      announcedIndexRef.current = tournament.currentLevel;
      const text =
        (level.announcementText || '').trim() ||
        'Please listen for table directions.';
      setLastSpoken(text);
      if (audioReady) speakNow(text);
    }

    // Land on announcement without levelChanged edge case (first paint)
    if (
      !levelChanged &&
      tournament.status === 'announcement' &&
      level.isAnnouncement &&
      announcedIndexRef.current !== tournament.currentLevel
    ) {
      announcedIndexRef.current = tournament.currentLevel;
      const text =
        (level.announcementText || '').trim() ||
        'Please listen for table directions.';
      setLastSpoken(text);
      if (audioReady) speakNow(text);
    }

    prevLevelRef.current = tournament.currentLevel;
    prevStatusRef.current = tournament.status;
  }, [
    tournament,
    displayRemaining,
    audioReady,
    triggerWarning,
    triggerLevelEndWithAnnouncement,
    triggerBreakAlarm,
    triggerBreakEnding,
    speakNow,
    resetWarning,
  ]);

  const applyRemaining = async () => {
    unlockAudio();
    setAudioReady(true);
    editingTimeRef.current = false;
    const m = Math.max(0, parseInt(editMinutes || '0', 10) || 0);
    const s = Math.max(0, Math.min(59, parseInt(editSeconds || '0', 10) || 0));
    await updateTournament('set_remaining', { seconds: m * 60 + s });
  };

  const playCustomAnnounce = () => {
    unlockAudio();
    setAudioReady(true);
    const text = customAnnounce.trim();
    if (!text) {
      setLastSpoken('(type an announcement first)');
      return;
    }
    speakNow(text, text);
  };

  const loadSpotify = async (url?: string) => {
    unlockAudio();
    setAudioReady(true);
    const raw = (url || spotifyInput).trim();
    const embed = toSpotifyEmbedUrl(raw);
    if (!embed) {
      alert('Paste a Spotify playlist, album, or track link.');
      return;
    }
    musicDuckedRef.current = false;
    setMusicMutedForSpeech(false);
    setSpotifyEmbed(embed);
    setSpotifyInput(raw);

    const history = pushSpotifyHistory(settings.spotifyPlaylistHistory, embed);
    setSettings((s) => ({ ...s, spotifyPlaylistHistory: history }));
    try {
      await fetch('/api/settings', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ spotifyPlaylistHistory: history }),
      });
    } catch {
      /* ignore */
    }
  };

  if (loading) {
    return (
      <div className="tip-screen min-h-screen flex items-center justify-center bg-felt-dark">
        <span className="text-poker-gold text-2xl">Loading TIP...</span>
      </div>
    );
  }

  if (!tournament) {
    return (
      <div className="tip-screen min-h-screen flex flex-col items-center justify-center gap-4 bg-felt-dark">
        <p className="text-white/70 text-xl">No active tournament</p>
        <Link href="/setup" className="btn-primary">
          Create Tournament
        </Link>
      </div>
    );
  }

  const level = getBlindLevelForState(tournament);
  const prizePool = getDisplayPrizePool(tournament);
  const payouts = getDisplayPayouts(tournament);
  // Break has its own countdown but is "stopped play" visually (red-ish via break UI + red when paused)
  const timerGoing =
    tournament.status === 'running' || tournament.status === 'announcement';
  const timerStopped =
    tournament.status === 'paused' ||
    tournament.status === 'registration' ||
    tournament.status === 'finished';
  const onBreak = tournament.status === 'break';

  const canEditTime =
    tournament.status === 'paused' || tournament.status === 'break';

  const bgClass = onBreak
    ? 'bg-gradient-to-br from-sky-950 via-blue-900 to-slate-950'
    : timerGoing
      ? 'bg-gradient-to-br from-green-900 via-green-800 to-emerald-950'
      : timerStopped
        ? 'bg-gradient-to-br from-red-950 via-red-900 to-rose-950'
        : 'felt-bg';

  return (
    <div
      className={`tip-screen min-h-screen flex flex-col transition-colors duration-500 ${bgClass}`}
      onPointerDown={() => {
        if (!audioReady) {
          unlockAudio();
          setAudioReady(true);
        }
      }}
    >
      {/* Step 1: enable browser audio (required before any announcement) */}
      {!audioReady && (
        <button
          type="button"
          className="w-full bg-amber-500 text-black font-bold py-4 text-base md:text-lg z-50 shadow-lg"
          onClick={handleEnableAudio}
        >
          🔊 Step 1 — Click to enable sounds &amp; announcements
        </button>
      )}

      {/* Step 2: start tournament only after audio is ready (registration) */}
      {audioReady && tournament.status === 'registration' && (
        <div className="w-full bg-green-700/90 border-b border-green-400/40 px-4 py-4 z-40 flex flex-col md:flex-row items-center justify-center gap-3">
          <p className="text-sm md:text-base text-green-50 text-center">
            Audio is ready. When players are seated, start the clock:
          </p>
          <button
            type="button"
            className="btn-primary text-base md:text-lg px-8 py-3 shadow-lg"
            onClick={handleStartTournament}
          >
            ▶ Start Tournament — Shuffle up &amp; deal
          </button>
        </div>
      )}

      {lastSpoken && (
        <div className="bg-black/70 border-b border-amber-400/40 px-4 py-2 text-center">
          <div className="text-[10px] uppercase tracking-wider text-amber-200/70">
            Last announcement
          </div>
          <div className="text-sm md:text-base text-white font-medium">{lastSpoken}</div>
        </div>
      )}

      <div className="flex flex-1 min-h-0">
        <div className="flex-1 p-4 md:p-6 overflow-auto">
          <TournamentDisplay tournament={tournament} remainingSeconds={displayRemaining} />

          <div className="mt-4 grid grid-cols-1 lg:grid-cols-2 gap-4">
            <div className="card border-white/10 space-y-2">
              <h3 className="text-sm font-semibold text-poker-gold">🎵 Spotify playlist</h3>
              <p className="text-xs text-white/50">
                Paste a Spotify link, then Play. During announcements music is paused
                (Spotify embeds cannot change volume from this page), then resumes.
                {musicMutedForSpeech ? ' (paused for announcement…)' : ''}
              </p>
              <div className="flex gap-2">
                <input
                  className="input-field flex-1 text-sm"
                  placeholder="https://open.spotify.com/playlist/…"
                  value={spotifyInput}
                  onChange={(e) => setSpotifyInput(e.target.value)}
                />
                <button type="button" className="btn-primary text-sm" onClick={() => loadSpotify()}>
                  Play
                </button>
              </div>
              {settings.spotifyPlaylistHistory.length > 0 && (
                <select
                  className="input-field text-sm"
                  value=""
                  onChange={(e) => {
                    if (e.target.value) loadSpotify(e.target.value);
                  }}
                >
                  <option value="">Previous playlists…</option>
                  {settings.spotifyPlaylistHistory.map((h) => (
                    <option key={h} value={h}>
                      {spotifyHistoryLabel(h)}
                    </option>
                  ))}
                </select>
              )}
              {spotifyEmbed && (
                <div
                  ref={spotifyHostRef}
                  className={`w-full rounded-lg border border-white/10 overflow-hidden transition-opacity ${
                    musicMutedForSpeech ? 'opacity-50' : 'opacity-100'
                  }`}
                  style={{ minHeight: 152 }}
                />
              )}
            </div>

            <div className="card border-white/10 space-y-2">
              <h3 className="text-sm font-semibold text-poker-gold">📣 Admin announcement</h3>
              <textarea
                className="input-field text-sm min-h-[4.5rem]"
                placeholder="Type what you want spoken…"
                value={customAnnounce}
                onChange={(e) => setCustomAnnounce(e.target.value)}
              />
              <button
                type="button"
                className="btn-primary w-full text-sm"
                onClick={playCustomAnnounce}
              >
                Speak custom announcement
              </button>
              <p className="text-[10px] text-white/40">
                Speaks the text you typed (plus a short beep). Enable the yellow bar once if
                speech was blocked.
              </p>
            </div>
          </div>
        </div>

        <div className="w-60 md:w-72 bg-black/55 border-l border-white/10 p-3 flex flex-col gap-3 overflow-y-auto flex-shrink-0">
          <LiveQRCode size={90} label="Live View QR" />

          <div
            className={`rounded-lg px-2 py-1.5 text-center text-xs font-bold uppercase tracking-wide ${
              onBreak
                ? 'bg-sky-500/30 text-sky-100 border border-sky-400/50'
                : timerGoing
                  ? 'bg-green-500/30 text-green-200 border border-green-400/40'
                  : 'bg-red-500/30 text-red-200 border border-red-400/40'
            }`}
          >
            {onBreak
              ? `TOURNAMENT ON BREAK · ${formatTime(displayRemaining)}`
              : `Timer ${timerGoing ? 'RUNNING' : 'STOPPED'} · ${formatTime(displayRemaining)}`}
          </div>
          {tournament.status === 'running' &&
            displayRemaining <= 60 &&
            displayRemaining > 0 && (
              <div className="rounded-lg px-2 py-2 text-center text-xs font-bold bg-orange-500/30 text-orange-100 border border-orange-400/50 animate-pulse">
                ⚠ Blinds go up in {formatTime(displayRemaining)}
              </div>
            )}

          <div className="border-t border-white/10 pt-2 space-y-2">
            <h3 className="text-xs uppercase tracking-wider text-white/50 font-semibold">
              Timer controls
            </h3>

            {(tournament.status === 'running' || tournament.status === 'announcement') && (
              <button
                onClick={() => {
                  unlockAudio();
                  setAudioReady(true);
                  updateTournament('pause');
                }}
                className="btn-secondary w-full text-sm"
              >
                ⏹ Stop / Pause
              </button>
            )}
            {tournament.status === 'paused' && (
              <button
                onClick={() => {
                  unlockAudio();
                  setAudioReady(true);
                  updateTournament('resume');
                }}
                className="btn-primary w-full text-sm"
              >
                ▶ Resume
              </button>
            )}
            {tournament.status === 'break' && (
              <button
                onClick={() => updateTournament('end_break')}
                className="btn-primary w-full text-sm"
              >
                ▶ End Break
              </button>
            )}
            {tournament.status === 'announcement' && (
              <button
                onClick={() => {
                  unlockAudio();
                  setAudioReady(true);
                  const t = getBlindLevelForState(tournament).announcementText;
                  if (t) speakNow(t);
                  updateTournament('end_announcement');
                }}
                className="btn-primary w-full text-sm"
              >
                ▶ Continue after announcement
              </button>
            )}
            {tournament.status === 'registration' && (
              <>
                {!audioReady ? (
                  <button
                    type="button"
                    onClick={handleEnableAudio}
                    className="w-full text-sm font-bold py-3 rounded-lg bg-amber-500 text-black"
                  >
                    🔊 Enable audio first
                  </button>
                ) : (
                  <button
                    type="button"
                    onClick={handleStartTournament}
                    className="btn-primary w-full text-sm py-3"
                  >
                    ▶ Start Tournament
                  </button>
                )}
                <p className="text-[10px] text-white/40 leading-snug">
                  Enable audio, then Start. That click announces “Shuffle up and deal.”
                </p>
              </>
            )}

            <div className="grid grid-cols-2 gap-2">
              <button
                onClick={() => updateTournament('previous_level')}
                className="btn-secondary w-full text-xs"
                disabled={tournament.currentLevel <= 0}
              >
                ⏮ Prev level
              </button>
              <button
                onClick={() => updateTournament('advance_level')}
                className="btn-secondary w-full text-xs"
              >
                ⏭ Next level
              </button>
            </div>
          </div>

          {/* Weekly bounty */}
          <div className="border-t border-white/10 pt-2 space-y-2">
            <h3 className="text-xs uppercase tracking-wider text-amber-400/80 font-semibold">
              🎯 Weekly bounty
            </h3>
            {tournament.entries.some((e) => e.hasBounty) ? (
              <>
                <div className="text-[11px] text-white/60 space-y-0.5">
                  {tournament.entries
                    .filter((e) => e.hasBounty)
                    .map((e) => (
                      <div key={e.id}>
                        Target: <span className="text-amber-200">{e.playerName}</span>
                        {' · '}
                        {e.bountyChips || '2000'} chips
                        {e.bountyCollected
                          ? ` · collected by ${e.bountyCollectedBy || '?'}`
                          : ''}
                      </div>
                    ))}
                </div>
                <select
                  className="input-field text-xs py-1.5"
                  value={bountyCollectorId}
                  onChange={(e) => setBountyCollectorId(e.target.value)}
                >
                  <option value="">Who collected bounty…</option>
                  {tournament.entries
                    .filter((e) => e.checkedIn)
                    .map((e) => (
                      <option key={e.id} value={e.id}>
                        {e.playerName}
                      </option>
                    ))}
                </select>
                <button
                  type="button"
                  onClick={handleBountyCollected}
                  disabled={!bountyCollectorId}
                  className="w-full text-xs font-bold py-2.5 rounded-lg bg-amber-600 hover:bg-amber-500 text-black disabled:opacity-40"
                >
                  🎯 Bounty Has Been Collected
                </button>
              </>
            ) : (
              <p className="text-[11px] text-white/40 leading-snug">
                Mark last week&apos;s winner with Bounty? on the Registration screen.
              </p>
            )}
          </div>

          <div className="border-t border-white/10 pt-2 space-y-2">
            <h3 className="text-xs uppercase tracking-wider text-white/50 font-semibold">
              Edit time remaining
            </h3>
            {!canEditTime ? (
              <p className="text-[11px] text-white/40 leading-snug">
                Stop the timer first, then set minutes:seconds and Apply (or +1 / −1 min).
              </p>
            ) : (
              <>
                <div className="flex items-center gap-1">
                  <input
                    className="input-field w-14 text-center text-sm py-1"
                    value={editMinutes}
                    onChange={(e) => {
                      editingTimeRef.current = true;
                      setEditMinutes(e.target.value.replace(/\D/g, ''));
                    }}
                    onFocus={() => {
                      editingTimeRef.current = true;
                    }}
                    inputMode="numeric"
                  />
                  <span className="text-white/60">:</span>
                  <input
                    className="input-field w-14 text-center text-sm py-1"
                    value={editSeconds}
                    onChange={(e) => {
                      editingTimeRef.current = true;
                      setEditSeconds(e.target.value.replace(/\D/g, '').slice(0, 2));
                    }}
                    onFocus={() => {
                      editingTimeRef.current = true;
                    }}
                    inputMode="numeric"
                  />
                  <button type="button" className="btn-primary text-xs flex-1" onClick={applyRemaining}>
                    Apply
                  </button>
                </div>
                <div className="grid grid-cols-2 gap-2">
                  <button
                    type="button"
                    className="btn-secondary text-xs"
                    onClick={async () => {
                      editingTimeRef.current = false;
                      await updateTournament('set_remaining', { deltaSeconds: 60 });
                    }}
                  >
                    +1 min
                  </button>
                  <button
                    type="button"
                    className="btn-secondary text-xs"
                    onClick={async () => {
                      editingTimeRef.current = false;
                      await updateTournament('set_remaining', { deltaSeconds: -60 });
                    }}
                  >
                    −1 min
                  </button>
                </div>
              </>
            )}
          </div>

          {/* Manual preset announcements — always available */}
          <div className="border-t border-white/10 pt-2 space-y-1.5">
            <h3 className="text-xs uppercase tracking-wider text-white/50 font-semibold">
              Structure announcements
            </h3>
            <p className="text-[10px] text-white/40">
              Replay anytime if someone missed it (does not move the clock).
            </p>
            {structureAnnouncements.length === 0 ? (
              <p className="text-[10px] text-white/30">
                No announcement rows in this structure. In Blinds: Level 2 → + Announcement →
                save → use that structure in Setup.
              </p>
            ) : (
              structureAnnouncements.map((a) => (
                <button
                  key={a.index}
                  type="button"
                  title={a.text}
                  className="btn-primary w-full text-xs text-left !bg-amber-700/80 hover:!bg-amber-600"
                  onClick={() => {
                    unlockAudio();
                    setAudioReady(true);
                    speakNow(a.text, `Play announcement ${a.n} now: ${a.text}`);
                  }}
                >
                  <div className="font-bold">▶ Play announcement {a.n} now</div>
                  <div className="text-[10px] text-white/80 truncate normal-case font-normal mt-0.5">
                    {a.text}
                  </div>
                </button>
              ))
            )}
          </div>

          <div className="border-t border-white/10 pt-2 space-y-2">
            <h3 className="text-xs uppercase tracking-wider text-white/50 font-semibold">
              Pool actions
            </h3>
            {tournament.config.rebuysEnabled && (
              <button
                onClick={() => updateTournament('rebuy')}
                className="btn-secondary w-full text-sm"
              >
                🔄 Record Rebuy
              </button>
            )}
            {tournament.config.addonsEnabled && (
              <button
                onClick={() => updateTournament('addon')}
                className="btn-secondary w-full text-sm"
              >
                ➕ Record Addon
              </button>
            )}
            <button
              onClick={() => updateTournament('pool_plus_one')}
              className="btn-primary w-full text-sm"
            >
              💰 Pool +1
            </button>
            <p className="text-[10px] text-white/40 leading-snug">
              <strong className="text-white/60">Pool +1:</strong> adds one rebuy (or addon) on the
              last checked-in player so the prize pool goes up by one unit without picking a name.
            </p>
          </div>

          {tournament.prizePoolLocked && payouts.length > 0 && (
            <div className="border-t border-white/10 pt-2">
              <h3 className="text-xs uppercase tracking-wider text-poker-gold font-semibold mb-2">
                🔒 Locked Payouts
              </h3>
              <div className="text-2xl font-bold text-green-400 mb-2">
                {formatCurrency(prizePool)}
              </div>
              {payouts.map((p) => (
                <div key={p.place} className="flex justify-between text-sm py-1">
                  <span className="text-white/60">#{p.place}</span>
                  <span className="font-bold text-green-400">
                    {p.amount !== undefined ? formatCurrency(p.amount) : `${p.percentage}%`}
                  </span>
                </div>
              ))}
            </div>
          )}

          <div className="border-t border-white/10 pt-2 mt-auto space-y-2">
            {tournament.status === 'registration' && (
              <Link href="/register" className="btn-secondary w-full text-sm block text-center">
                Registration
              </Link>
            )}
            <button
              onClick={() => {
                if (
                  confirm(
                    'Restart tournament?\n\nThis resets the clock to the first level and returns to registration. Players stay on the list. This cannot be undone.'
                  )
                ) {
                  if (confirm('Are you sure? Restart will reset levels, breaks, and prize-pool lock.')) {
                    updateTournament('restart').then(() => {
                      try {
                        sessionStorage.removeItem(`pokerforge_shuffle_${tournament.id}`);
                      } catch {
                        /* ignore */
                      }
                      shuffleSpokenForId.current = null;
                      setLastSpoken('Tournament restarted — ready for registration / Start.');
                    });
                  }
                }
              }}
              className="btn-secondary w-full text-sm border border-amber-500/40"
            >
              🔄 Restart tournament
            </button>
            <button
              onClick={() => {
                if (confirm('Finish tournament and save to history?')) {
                  updateTournament('finish');
                }
              }}
              className="btn-danger w-full text-sm"
            >
              🏁 Finish (save to History)
            </button>
            <button
              onClick={() => {
                if (
                  confirm(
                    tournament.status === 'finished'
                      ? 'Clear this tournament from the live dashboard?\n\nHistory is kept under History. You can start a new tournament after this.'
                      : 'Clear the active tournament without saving?\n\nUse Finish first if you want it in History.'
                  )
                ) {
                  updateTournament('clear').then(() => {
                    window.location.href = '/';
                  });
                }
              }}
              className="btn-secondary w-full text-sm"
            >
              📦 Clear / dismiss active game
            </button>
            <Link href="/" className="text-xs text-white/40 hover:text-white/70 block text-center">
              ← Dashboard
            </Link>
          </div>
        </div>
      </div>

      <div className="bg-black/70 px-4 py-2 flex items-center justify-between text-xs text-white/60 border-t border-white/10">
        <span>
          {level.isAnnouncement
            ? `📣 ${level.announcementText?.slice(0, 60) || 'Announcement'}…`
            : level.isBreak
              ? level.breakLabel
              : `Level ${level.level} · ${formatBlinds(level)}`}
        </span>
        <span className="capitalize font-semibold">
          {tournament.status}
          {timerGoing ? ' · 🟢' : ' · 🔴'}
        </span>
        <span>
          E:{tournament.totalEntries} R:{tournament.totalRebuys} A:{tournament.totalAddons} ·{' '}
          {formatCurrency(prizePool)}
        </span>
      </div>
    </div>
  );
}
