import { useCallback, useEffect, useRef, useState } from "react";
import type {
  AudioConstraints,
  MicrophoneHookReturn,
  MicrophoneOptions,
  VolumeData,
} from "./index.type";

export const useMicrophone = (options: MicrophoneOptions = {}): MicrophoneHookReturn => {
  const {
    updateInterval = 50,
    fftSize = 1024,
    onVolumeChange = null,
    threshold = 10,
    smoothing = 0.3,
    volumeScale = 150,
  } = options;

  const [volume, setVolume] = useState<number>(0);
  const [smoothedVolume, setSmoothedVolume] = useState<number>(0);
  const [isListening, setIsListening] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const [isSpeaking, setIsSpeaking] = useState<boolean>(false);

  const audioContextRef = useRef<AudioContext | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const analyserRef = useRef<AnalyserNode | null>(null);
  const intervalRef = useRef<any>(null);
  const dataArrayRef = useRef<any>(null);
  const previousVolumeRef = useRef<number>(0);

  // 改进的音量计算方法
  const calculateVolume = useCallback(
    (dataArray: any): number => {
      let sum = 0;
      let max = 0;

      // 计算RMS（均方根）和峰值
      for (let i = 0; i < dataArray.length; i++) {
        const sample = (dataArray[i] - 128) / 128; // 归一化到 -1 到 1
        sum += sample * sample;
        max = Math.max(max, Math.abs(sample));
      }

      const rms = Math.sqrt(sum / dataArray.length);

      // 使用RMS和峰值的组合，并应用缩放
      const calculatedVolume = (rms * 0.7 + max * 0.3) * volumeScale;

      return Math.min(calculatedVolume, 100); // 限制最大值为100
    },
    [volumeScale]
  );

  // 改进的平滑处理
  const smoothVolume = useCallback(
    (currentVolume: number): number => {
      const smoothed = previousVolumeRef.current * smoothing + currentVolume * (1 - smoothing);
      previousVolumeRef.current = smoothed;
      return smoothed;
    },
    [smoothing]
  );

  // 开始监听麦克风
  const startListening = useCallback(async (): Promise<void> => {
    try {
      setError(null);

      // 检查浏览器支持
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        throw new Error("浏览器不支持麦克风访问");
      }

      // 创建AudioContext
      const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;
      if (!AudioContextClass) {
        throw new Error("浏览器不支持AudioContext");
      }

      audioContextRef.current = new AudioContextClass();

      // 音频约束配置
      const audioConstraints: AudioConstraints = {
        echoCancellation: false, // 关闭回声消除
        noiseSuppression: false, // 关闭噪声抑制
        autoGainControl: false, // 关闭自动增益控制
      };

      // 请求麦克风权限
      streamRef.current = await navigator.mediaDevices.getUserMedia({
        audio: audioConstraints,
      });

      // 创建音频源和分析器
      const source = audioContextRef.current?.createMediaStreamSource(streamRef.current);
      audioContextRef.current.resume();
      analyserRef.current = audioContextRef.current?.createAnalyser();
      source.connect(analyserRef.current);

      // 优化分析器设置
      analyserRef.current.fftSize = fftSize;
      analyserRef.current.smoothingTimeConstant = 0.1; // 降低内置平滑

      const bufferLength = analyserRef.current.frequencyBinCount;
      dataArrayRef.current = new Uint8Array(bufferLength);

      setIsListening(true);

      // 定时获取音量数据
      intervalRef.current = setInterval(() => {
        if (analyserRef.current && dataArrayRef.current) {
          analyserRef.current.getByteTimeDomainData(dataArrayRef.current);
          const currentVolume = calculateVolume(dataArrayRef.current);
          const smoothed = smoothVolume(currentVolume);

          setVolume(currentVolume);
          setSmoothedVolume(smoothed);
          setIsSpeaking(smoothed > threshold);

          // 触发回调
          if (onVolumeChange) {
            const volumeData: VolumeData = {
              volume: currentVolume,
              smoothedVolume: smoothed,
              isSpeaking: smoothed > threshold,
            };
            onVolumeChange(volumeData);
          }
        }
      }, updateInterval);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : "未知错误";
      console.error("Error accessing microphone:", err);
      setError(errorMessage);
    }
  }, [calculateVolume, smoothVolume, fftSize, updateInterval, threshold, onVolumeChange]);

  // 停止监听麦克风
  const stopListening = useCallback((): void => {
    // 清除定时器
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }

    // 停止音频流
    if (streamRef.current) {
      streamRef.current.getTracks().forEach(track => track.stop());
      streamRef.current = null;
    }

    // 关闭AudioContext
    if (audioContextRef.current) {
      audioContextRef.current.close();
      audioContextRef.current = null;
    }

    setIsListening(false);
    setVolume(0);
    setSmoothedVolume(0);
    setIsSpeaking(false);
    previousVolumeRef.current = 0;
  }, []);

  // 组件卸载时清理资源
  useEffect(() => {
    return () => {
      stopListening();
    };
  }, [stopListening]);

  return {
    volume,
    smoothedVolume,
    isListening,
    error,
    isSpeaking,
    startListening,
    stopListening,
  };
};
