import { useState, useRef, useCallback, useEffect } from 'react'

// TypeScript declarations for Web Speech API
declare global {
  interface Window {
    SpeechRecognition: typeof SpeechRecognition
    webkitSpeechRecognition: typeof SpeechRecognition
  }

  interface SpeechRecognition extends EventTarget {
    continuous: boolean
    interimResults: boolean
    lang: string
    maxAlternatives: number
    start(): void
    stop(): void
    onstart: ((this: SpeechRecognition, ev: Event) => void) | null
    onresult: ((this: SpeechRecognition, ev: SpeechRecognitionEvent) => void) | null
    onerror: ((this: SpeechRecognition, ev: SpeechRecognitionErrorEvent) => void) | null
    onend: ((this: SpeechRecognition, ev: Event) => void) | null
  }

  interface SpeechRecognitionEvent extends Event {
    resultIndex: number
    results: SpeechRecognitionResultList
  }

  interface SpeechRecognitionErrorEvent extends Event {
    error: string
  }

  interface SpeechRecognitionResultList {
    readonly length: number
    item(index: number): SpeechRecognitionResult
    [index: number]: SpeechRecognitionResult
  }

  interface SpeechRecognitionResult {
    readonly length: number
    item(index: number): SpeechRecognitionAlternative
    [index: number]: SpeechRecognitionAlternative
    readonly isFinal: boolean
  }

  interface SpeechRecognitionAlternative {
    readonly transcript: string
    readonly confidence: number
  }

  // eslint-disable-next-line no-var
  var SpeechRecognition: {
    prototype: SpeechRecognition
    new(): SpeechRecognition
  }
}

interface UseWebSpeechTranscriptionOptions {
  onTranscriptUpdate?: (text: string) => void
  onError?: (error: Error) => void
  language?: string
  continuous?: boolean
  interimResults?: boolean
}

export const useWebSpeechTranscription = ({
  onTranscriptUpdate,
  onError,
  language = 'en-US',
  continuous = true,
  interimResults = true
}: UseWebSpeechTranscriptionOptions = {}) => {
  const [isRecording, setIsRecording] = useState(false)
  const [transcript, setTranscript] = useState('')
  const [interimTranscript, setInterimTranscript] = useState('')
  const [isSupported, setIsSupported] = useState(false)

  const recognitionRef = useRef<SpeechRecognition | null>(null)
  const finalTranscriptRef = useRef('')
  const lastSpeechTimeRef = useRef<number>(0)

  // Process transcript with line breaks after pauses
  const processTranscript = useCallback((text: string, isFinal: boolean = false) => {
    if (!text.trim()) return text

    let processedText = text.trim()

    // Add punctuation if missing at the end
    if (isFinal && processedText && !/[.!?]$/.test(processedText)) {
      processedText += '.'
    }

    // Add line break if there's been a pause
    if (isFinal) {
      const now = Date.now()
      const timeSinceLastSpeech = now - lastSpeechTimeRef.current

      if (timeSinceLastSpeech > 3000 && lastSpeechTimeRef.current > 0) {
        processedText = '\n\n' + processedText
      }

      lastSpeechTimeRef.current = now
    }

    return processedText
  }, [])

  // Check if Web Speech API is supported
  useEffect(() => {
    const SpeechRecognitionAPI = window.SpeechRecognition || window.webkitSpeechRecognition
    if (SpeechRecognitionAPI) {
      setIsSupported(true)
    } else {
      setIsSupported(false)
      onError?.(new Error('Web Speech API is not supported in this browser. Try Chrome or Edge.'))
    }
  }, [onError])

  // Initialize speech recognition
  const initializeRecognition = useCallback(() => {
    if (!isSupported) return null

    const SpeechRecognitionAPI = window.SpeechRecognition || window.webkitSpeechRecognition
    const recognition = new SpeechRecognitionAPI()

    recognition.continuous = continuous
    recognition.interimResults = interimResults
    recognition.lang = language
    recognition.maxAlternatives = 1

    recognition.onstart = () => {
      setIsRecording(true)
    }

    recognition.onresult = (event) => {
      let interim = ''
      let final = ''

      for (let i = event.resultIndex; i < event.results.length; i++) {
        const result = event.results[i]
        const text = result[0].transcript

        if (result.isFinal) {
          final += text
        } else {
          interim += text
        }
      }

      if (final) {
        const processedFinal = processTranscript(final, true)
        finalTranscriptRef.current += processedFinal + ' '
        setTranscript(finalTranscriptRef.current)
        onTranscriptUpdate?.(processedFinal)
      }

      if (interim) {
        setInterimTranscript(processTranscript(interim, false))
      }
    }

    recognition.onerror = (event) => {
      console.error('Speech recognition error:', event.error)
      setIsRecording(false)

      if (event.error !== 'aborted') {
        onError?.(new Error(`Speech recognition error: ${event.error}`))
      }
    }

    recognition.onend = () => {
      setIsRecording(false)
      setInterimTranscript('')
    }

    return recognition
  }, [isSupported, continuous, interimResults, language, onTranscriptUpdate, onError, processTranscript])

  // Start recording
  const startRecording = useCallback(() => {
    if (!isSupported) {
      onError?.(new Error('Web Speech API is not supported'))
      return
    }

    try {
      lastSpeechTimeRef.current = 0

      const recognition = initializeRecognition()
      if (recognition) {
        recognitionRef.current = recognition
        recognition.start()
      }
    } catch (error) {
      console.error('Error starting speech recognition:', error)
      onError?.(error as Error)
    }
  }, [isSupported, initializeRecognition, onError])

  // Stop recording
  const stopRecording = useCallback(() => {
    if (recognitionRef.current) {
      recognitionRef.current.stop()
      recognitionRef.current = null
    }
  }, [])

  // Clear transcript
  const clearTranscript = useCallback(() => {
    finalTranscriptRef.current = ''
    setTranscript('')
    setInterimTranscript('')
  }, [])

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (recognitionRef.current) {
        recognitionRef.current.stop()
        recognitionRef.current = null
      }
    }
  }, [])

  return {
    isRecording,
    transcript,
    interimTranscript,
    isSupported,
    startRecording,
    stopRecording,
    clearTranscript
  }
}

export default useWebSpeechTranscription
