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

interface AudioActivityConfig {
  threshold?: number // 音频阈值，默认 30
  sampleRate?: number // 采样率，默认 100ms
  smoothingTimeConstant?: number // 平滑常数，默认 0.8
  fftSize?: number // FFT 大小，默认 1024
}

interface UseAudioActivityDetectionReturn {
  isDetecting: boolean
  isSpeaking: boolean
  audioLevel: number
  startDetection: (stream: MediaStream) => void
  stopDetection: () => void
  error: string | null
}

export function useAudioActivityDetection(
  config: AudioActivityConfig = {}
): UseAudioActivityDetectionReturn {
  const { threshold = 30, sampleRate = 100, smoothingTimeConstant = 0.8, fftSize = 1024 } = config

  const [isDetecting, setIsDetecting] = useState(false)
  const [isSpeaking, setIsSpeaking] = useState(false)
  const [audioLevel, setAudioLevel] = useState(0)
  const [error, setError] = useState<string | null>(null)

  const audioContextRef = useRef<AudioContext | null>(null)
  const analyserRef = useRef<AnalyserNode | null>(null)
  const microphoneRef = useRef<MediaStreamAudioSourceNode | null>(null)
  const animationFrameRef = useRef<number | null>(null)
  const intervalRef = useRef<NodeJS.Timeout | null>(null)

  // 音频分析函数
  const analyzeAudio = useCallback(() => {
    if (!analyserRef.current) return

    const analyser = analyserRef.current
    const bufferLength = analyser.frequencyBinCount
    const dataArray = new Uint8Array(bufferLength)

    const checkAudioLevel = () => {
      if (!analyser) return

      analyser.getByteFrequencyData(dataArray)

      // 计算平均音量
      let sum = 0
      for (let i = 0; i < bufferLength; i++) {
        sum += dataArray[i]
      }
      const average = sum / bufferLength

      setAudioLevel(average)

      // 判断是否在说话
      const currentlySpeaking = average > threshold
      setIsSpeaking(currentlySpeaking)

      // 调试日志
      if (process.env.NODE_ENV === 'development') {
        // console.log('Audio Level:', average, 'Speaking:', currentlySpeaking);
      }
    }

    // 使用定时器而不是 requestAnimationFrame 以确保稳定的采样率
    intervalRef.current = setInterval(checkAudioLevel, sampleRate)
  }, [threshold, sampleRate])

  // 开始检测
  const startDetection = useCallback(
    async (stream: MediaStream) => {
      try {
        setError(null)

        // 创建音频上下文
        if (!audioContextRef.current) {
          audioContextRef.current = new (
            window.AudioContext || (window as any).webkitAudioContext
          )()
        }

        const audioContext = audioContextRef.current

        // 确保音频上下文处于运行状态
        if (audioContext.state === 'suspended') {
          await audioContext.resume()
        }

        // 创建分析器
        const analyser = audioContext.createAnalyser()
        analyser.smoothingTimeConstant = smoothingTimeConstant
        analyser.fftSize = fftSize

        // 创建音频源
        const microphone = audioContext.createMediaStreamSource(stream)
        microphone.connect(analyser)

        analyserRef.current = analyser
        microphoneRef.current = microphone

        setIsDetecting(true)
        analyzeAudio()

        console.log('音频活动检测已启动')
      } catch (err) {
        console.error('启动音频检测失败:', err)
        setError(err instanceof Error ? err.message : '启动音频检测失败')
      }
    },
    [analyzeAudio, smoothingTimeConstant, fftSize]
  )

  // 停止检测
  const stopDetection = useCallback(() => {
    // 清除定时器
    if (intervalRef.current) {
      clearInterval(intervalRef.current)
      intervalRef.current = null
    }

    // 清除动画帧
    if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current)
      animationFrameRef.current = null
    }

    // 断开音频连接
    if (microphoneRef.current) {
      microphoneRef.current.disconnect()
      microphoneRef.current = null
    }

    // 清理分析器
    analyserRef.current = null

    // 关闭音频上下文
    if (audioContextRef.current && audioContextRef.current.state !== 'closed') {
      audioContextRef.current.close()
      audioContextRef.current = null
    }

    setIsDetecting(false)
    setIsSpeaking(false)
    setAudioLevel(0)
    setError(null)

    console.log('音频活动检测已停止')
  }, [])

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      stopDetection()
    }
  }, [stopDetection])

  return {
    isDetecting,
    isSpeaking,
    audioLevel,
    startDetection,
    stopDetection,
    error,
  }
}
