import { useWebSocketStore } from "@/services";
import { convertToPCM16 } from "@/utils";
import { useChatStore } from "./chat_store";

export const useAsrStore = defineStore("asr", () => {
  // 是否正在录音
  const isRecording = ref(false);
  // 识别结果消息列表
  const messages = ref<string[]>([]);
  // 音频相关对象
  let audioContext: AudioContext | null = null;
  let mediaStreamSource: MediaStreamAudioSourceNode | null = null;
  let workletNode: AudioWorkletNode | null = null;

  const webSocketStore = useWebSocketStore();
  const router = useRouter();

  /**
   * 发送消息到 WebSocket
   * @param data 字符串或二进制数据
   */
  const sendMessage = (data: string | Uint8Array) => {
    // 仅在连接已建立时发送
    if (webSocketStore.connected) {
      if (typeof data === "string") {
        webSocketStore.send(data);
      } else {
        webSocketStore.websocket?.send(data);
      }
    }
  };

  // AudioWorklet 处理器代码，作为字符串
  const audioProcessorCode = `
    class AudioProcessor extends AudioWorkletProcessor {
      process(inputs, outputs, parameters) {
        const input = inputs[0]
        if (input.length > 0) {
          const inputChannel = input[0]
          // 发送音频数据到主线程
          this.port.postMessage({
            type: 'audiodata',
            data: inputChannel
          })
        }
        return true
      }
    }
    registerProcessor('audio-processor', AudioProcessor)
  `;

  /**
   * 开始录音
   */
  const startRecording = async () => {
    if (isRecording.value) return;
    messages.value = [];
    // 确保 WebSocket 已连接
    if (!webSocketStore.connected) {
      webSocketStore.connect();
      // 等待连接建立
      await new Promise<void>((resolve) => {
        const check = () => {
          if (webSocketStore.connected) resolve();
          else setTimeout(check, 100);
        };
        check();
      });
    }
    try {
      // 获取麦克风音频流
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      // 创建音频上下文，采样率16kHz
      audioContext = new (window.AudioContext ||
        (window as any).webkitAudioContext)({
        sampleRate: 16000
      });
      // 用Blob方式创建AudioWorklet模块的URL
      const blob = new Blob([audioProcessorCode], {
        type: "application/javascript"
      });
      const processorUrl = URL.createObjectURL(blob);
      // 加载AudioWorklet模块
      await audioContext.audioWorklet.addModule(processorUrl);
      // 释放URL对象防止内存泄漏
      URL.revokeObjectURL(processorUrl);

      // 创建音频源节点
      mediaStreamSource = audioContext.createMediaStreamSource(stream);

      // 创建AudioWorkletNode
      workletNode = new AudioWorkletNode(audioContext, "audio-processor", {
        numberOfInputs: 1,
        numberOfOutputs: 1,
        channelCount: 1
      });

      // 监听来自AudioWorklet的音频数据
      workletNode.port.onmessage = (event) => {
        if (event.data.type === "audiodata") {
          // 转换为16位PCM格式
          const pcmData = convertToPCM16(event.data.data);
          // 发送PCM数据到WebSocket
          sendMessage(pcmData);
        }
      };
      // 连接音频节点
      mediaStreamSource.connect(workletNode);
      workletNode.connect(audioContext.destination);
      isRecording.value = true;
    } catch (err) {
      // 麦克风权限失败或AudioWorklet加载失败
      console.error("需要麦克风权限才能录音", err);
    }
  };

  /**
   * 停止录音
   */
  const stopRecording = () => {
    if (!isRecording.value) return;

    const messageId = `voice_${Date.now()}`;
    // 通知后端录音结束
    const msg: Record<string, any> = { type: "asr_end" };
    if (router.currentRoute.value.path === "/voice") {
      msg.messageId = messageId;
      msg.voiceConversation = true;
      msg.speaker = useChatStore().speakerInfo?.speaker_id;
    }
    sendMessage(JSON.stringify(msg));

    // 停止所有音轨
    if (mediaStreamSource?.mediaStream) {
      const tracks = mediaStreamSource.mediaStream.getTracks();
      tracks.forEach((track) => track.stop());
    }

    // 断开音频节点
    workletNode?.disconnect();
    mediaStreamSource?.disconnect();
    setTimeout(() => {
      // TODO: 临时写法，这里的更新状态需要调整
      // 确保在停止录音后延迟更新状态，因为要等待LLM请求
      isRecording.value = false;
    }, 300);

    // 释放音频资源
    audioContext?.close().then(() => {
      audioContext = null;
      mediaStreamSource = null;
      workletNode = null;
    });
  };

  return {
    isRecording,
    messages,
    startRecording,
    stopRecording,
    sendMessage
  };
});
