import { useState, useCallback, useMemo, useEffect, useRef } from "react";
import { Masthead } from "../components/Masthead";
import { SpeakerPanel } from "../components/listen/SpeakerPanel";
import { TranscriptPanel } from "../components/listen/TranscriptPanel";
import { ControlPanel } from "../components/listen/ControlPanel";
import { useMicrophone } from "../hooks/useMicrophone";
import { useWebSocket } from "../hooks/useWebSocket";

export default function ListenPage() {
  const [isListening, setIsListening] = useState(false);
  const [activeSpeaker, setActiveSpeaker] = useState<string | null>(null);
  const [permissionRequested, setPermissionRequested] = useState(false);
  const isListeningRef = useRef(false);

  // Keep ref in sync with state for use in callbacks
  useEffect(() => {
    isListeningRef.current = isListening;
  }, [isListening]);

  const ws = useWebSocket({
    onTranscript: (transcript) => {
      // Track active speaker
      if (!transcript.isFinal) {
        setActiveSpeaker(transcript.speaker);
      }
    },
    onStopped: () => {
      setIsListening(false);
      setActiveSpeaker(null);
    },
  });

  const wsRef = useRef(ws);
  useEffect(() => {
    wsRef.current = ws;
  }, [ws]);

  const handleAudioData = useCallback((samples: Float32Array) => {
    if (wsRef.current.isConnected && isListeningRef.current) {
      wsRef.current.sendAudio(samples);
    }
  }, []);

  const mic = useMicrophone({
    sampleRate: 16000,
    onAudioData: handleAudioData,
  });

  // Request microphone permission on page load
  useEffect(() => {
    if (!permissionRequested) {
      setPermissionRequested(true);
      mic.requestPermission();
    }
  }, [permissionRequested, mic.requestPermission]);

  // Derive unique speakers from transcripts
  const speakers = useMemo(() => {
    const speakerSet = new Set<string>();
    ws.transcripts.forEach((t) => speakerSet.add(t.speaker));

    return Array.from(speakerSet).map((speaker) => ({
      id: speaker,
      label: speaker,
      isActive: speaker === activeSpeaker,
    }));
  }, [ws.transcripts, activeSpeaker]);

  // Clear active speaker after a delay
  useEffect(() => {
    if (activeSpeaker) {
      const timer = setTimeout(() => setActiveSpeaker(null), 1500);
      return () => clearTimeout(timer);
    }
  }, [activeSpeaker]);

  const handleToggle = useCallback(async () => {
    if (isListening) {
      // Stop listening
      mic.stop();
      ws.stopSession("user_stopped");
      setIsListening(false);
      setActiveSpeaker(null);
      return;
    }

    // If permission was denied or errored, try requesting again
    if (mic.status === "denied" || mic.status === "error") {
      const permitted = await mic.requestPermission();
      if (!permitted) {
        return;
      }
    }

    // Start listening - start the microphone
    const micStarted = await mic.start();
    if (!micStarted) {
      // Microphone permission denied or error
      return;
    }

    // Microphone started, now connect to WebSocket
    const connected = await ws.connect();
    if (!connected) {
      // Connection failed - stop the microphone
      mic.stop();
      return;
    }

    // Both microphone and WebSocket are ready - start the session
    ws.startSession(mic.sampleRate, mic.channels);
    setIsListening(true);
  }, [isListening, mic, ws]);

  const handleNew = useCallback(() => {
    // Stop current session - backend auto-saves transcript on disconnect
    mic.stop();
    if (ws.isConnected) {
      ws.stopSession("new_session");
    }
    ws.clearTranscripts();
    ws.disconnect();
    setIsListening(false);
    setActiveSpeaker(null);
  }, [mic, ws]);

  const error = ws.error || mic.error;

  return (
    <div className="relative z-10 h-screen flex flex-col overflow-hidden">
      <Masthead showTicker={false} showNav />

      <main className="flex-1 p-4 md:p-6 grid grid-cols-1 md:grid-cols-[300px_1fr] grid-rows-[minmax(0,1fr)_auto] md:grid-rows-[minmax(0,1fr)_auto] gap-4 min-h-0 overflow-hidden">
        {/* Speaker Panel - top left on desktop, hidden on mobile */}
        <div className="hidden md:block row-span-1 min-h-0 overflow-hidden">
          <SpeakerPanel speakers={speakers} />
        </div>

        {/* Transcript Panel - right side, spans 2 rows on desktop */}
        <div className="md:row-span-2 min-h-0 overflow-hidden">
          <TranscriptPanel transcripts={ws.transcripts} />
        </div>

        {/* Control Panel - bottom left on desktop */}
        <div className="md:col-start-1 md:row-start-2 shrink-0">
          <ControlPanel
            isListening={isListening}
            isConnected={ws.isConnected}
            micStatus={mic.status}
            micVolume={mic.volume}
            hasTranscripts={ws.transcripts.length > 0}
            onToggle={handleToggle}
            onNew={handleNew}
            error={error}
          />
        </div>
      </main>
    </div>
  );
}
