import { useCallback, useEffect, useRef, useState } from "react";

export interface UseVoiceSearchResult {
  isListening: boolean;
  transcript: string;
  isSupported: boolean;
  hasError: boolean;
  errorMessage: string | null;
  startListening: () => void;
  stopListening: () => void;
}

/**
 * Hook for voice search using the Web Speech API.
 * Returns a microphone control interface.
 * Gracefully degrades when SpeechRecognition is unavailable.
 */
export function useVoiceSearch(): UseVoiceSearchResult {
  const [isListening, setIsListening] = useState(false);
  const [transcript, setTranscript] = useState("");
  const [isSupported, setIsSupported] = useState(false);
  const [hasError, setHasError] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  const recognitionRef = useRef<SpeechRecognition | null>(null);
  const mountedRef = useRef(true);

  useEffect(() => {
    mountedRef.current = true;
    // Check for SpeechRecognition support (standard + webkit prefix)
    const SpeechRecognitionCtor =
      (window as unknown as Record<string, unknown>).SpeechRecognition ??
      (window as unknown as Record<string, unknown>).webkitSpeechRecognition;

    if (typeof SpeechRecognitionCtor === "function") {
      setIsSupported(true);
      const recognition = new (SpeechRecognitionCtor as new () => SpeechRecognition)();
      recognition.continuous = false;
      recognition.interimResults = false;
      recognition.lang = "en-US";

      recognition.onresult = (event: SpeechRecognitionEvent) => {
        const resultText = event.results[0]?.[0]?.transcript ?? "";
        if (mountedRef.current) {
          setTranscript(resultText);
          setHasError(false);
          setErrorMessage(null);
        }
      };

      recognition.onerror = (event: SpeechRecognitionErrorEvent) => {
        if (mountedRef.current) {
          setHasError(true);
          setErrorMessage(event.error);
          setIsListening(false);
        }
      };

      recognition.onend = () => {
        if (mountedRef.current) {
          setIsListening(false);
        }
      };

      recognitionRef.current = recognition;
    }

    return () => {
      mountedRef.current = false;
      if (recognitionRef.current) {
        recognitionRef.current.abort();
      }
    };
  }, []);

  const startListening = useCallback(() => {
    if (!recognitionRef.current) return;
    setTranscript("");
    setHasError(false);
    setErrorMessage(null);
    try {
      recognitionRef.current.start();
      setIsListening(true);
    } catch {
      // May throw if already started
      setIsListening(false);
    }
  }, []);

  const stopListening = useCallback(() => {
    if (!recognitionRef.current) return;
    recognitionRef.current.stop();
    setIsListening(false);
  }, []);

  return {
    isListening,
    transcript,
    isSupported,
    hasError,
    errorMessage,
    startListening,
    stopListening,
  };
}