import React, { useState, useEffect, useRef, useCallback } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { PhoneFill, LocationOutline } from "antd-mobile-icons";
import './AiChatStyles.less';
import { Toast, Input, Tabs, Selector, Grid, Image, Button, Checkbox, Switch, Dialog, Radio, Space, CenterPopup, ImageViewer, Collapse, CapsuleTabs } from "antd-mobile";
import VConsole from 'vconsole';
let vConsole;
const ChatInterface = () => {
  // ==================== 状态管理 ====================
  const [sessionId, setSessionId] = useState('');
  const [sUserId] = useState('user-001');
  const [sUserType] = useState('sysadmin');
  const [messages, setMessages] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const [currentModel, setCurrentModel] = useState('general');
  const [chatHistory, setChatHistory] = useState([]);
  const [welcomeContent, setWelcomeContent] = useState('');
  const phoneContentRef = useRef(null);
  //  vConsole = new VConsole();


  // 语音输入状态
  const [isRecording, setIsRecording] = useState(false);
  const [isAiRecording, setIsAiRecording] = useState(false);
  const [isRecordingModel, setIsRecordingModel] = useState(false);
  const [isWsConnected, setIsWsConnected] = useState(false);
  const [isVoiceMode, setIsVoiceMode] = useState(false);
  const [recordingDuration, setRecordingDuration] = useState(0);
  const [isFlushing, setIsFlushing] = useState(false);

  // ==================== 新增：语音模式下的临时对话展示 ====================
  const [voiceMessages, setVoiceMessages] = useState([]); // 存储语音模式下的对话

  const silenceTimeoutRef = useRef(null); // 静默超时定时器
  const resetSilenceTimeoutRef = useRef(null);

  const messagesEndRef = useRef(null);
  const inputRef = useRef(null);
  const wsRef = useRef(null);
  const audioContextRef = useRef(null);
  const scriptProcessorRef = useRef(null);
  const inputNodeRef = useRef(null);
  const recordingTimerRef = useRef(null);
  const isRecordingRef = useRef(false);
  // ==================== 关键修复：使用 ref 存储最新输入值 ====================
  const inputValueRef = useRef(inputValue);

  // ==================== 配置 ====================
  const CONFIG = {
    backendUrl: 'http://localhost:8099/xlyAi',
    wsUrl: 'ws://121.43.128.225:10096', // 语音识别WebSocket地址
    sampleRate: 16000,
    endpoints: {
      chat: '/api/v1/chat/query',
      process: '/api/v1/chat/query',
    },
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    },
    maxHistory: 20,
  };

  // ==================== 工具函数 ====================
  const getCurrentTime = () => {
    const now = new Date();
    return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
  };

  const generateRandomString = (length) => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  };

  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  };

  // ==================== WebSocket 语音识别 ====================

  // 连接语音识别WebSocket
  const connectWebSocket = useCallback(() => {
    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
      return;
    }

    const ws = new WebSocket(CONFIG.wsUrl);
    ws.binaryType = "arraybuffer";

    ws.onopen = () => {
      console.log("语音识别WebSocket连接成功");
      setIsWsConnected(true);
    };

    ws.onmessage = (event) => {
      try {
        const res = JSON.parse(event.data);
        if (res.code === 0) {
          // 处理普通识别结果
          if ((res.msg === "success" || res.msg === "partial") && res.text?.trim()) {
            if (wsRef.current) {
              wsRef.current.hasReceivedSpeech = true;
            }
            // ==================== 关键修复：更新 ref 和 state ====================
            const newValue = inputValueRef.current
              ? `${inputValueRef.current} ${res.text}`.trim()
              : res.text;
            inputValueRef.current = newValue;
            setInputValue(newValue);

            // 重置静默检测（收到语音后重新计时2秒）
            resetSilenceTimeout();
          }

          // 👇 新增：处理 flush 完成
          if (res.msg === "flush_success") {
            console.log("Flush 完成，语音识别结束");
            // 延迟一点确保所有消息处理完毕
            setTimeout(() => {
              setIsFlushing(false);
              // 只有在语音模式下才清空（避免干扰手动输入）
              if (isVoiceMode) {
                setInputValue('');
                inputValueRef.current = '';
              }
            }, 100);
          }
        }
      } catch (e) {
        console.error("WebSocket消息解析失败:", e);
      }
    };

    ws.onclose = () => {
      console.log("语音识别WebSocket连接断开");
      setIsWsConnected(false);
      if (isRecordingRef.current) {
        stopRecordingOnly();
      }
    };

    ws.onerror = (err) => {
      console.error("WebSocket错误:", err);
      setIsWsConnected(false);
    };

    wsRef.current = ws;
  }, []);

  // ==================== 关键修复：重置静默检测定时器 ====================
  const resetSilenceTimeout = useCallback(() => {
    // 清除旧的定时器
    if (silenceTimeoutRef.current) {
      clearTimeout(silenceTimeoutRef.current);
    }

    // 重新设置2秒静默检测
    silenceTimeoutRef.current = setTimeout(() => {
      console.log('2秒内未检测到语音，自动处理');
      const latestInput = inputValueRef.current.trim();
      console.log("🚀 ～ 当前输入值:", latestInput);

      if (latestInput) {
        handleSendMessageWithContent(latestInput);
      } else {
        // 没有内容：仅停止当前录音，不清空弹窗，也不关闭 isRecordingModel
        stopRecordingOnly();
        Toast.show('未检测到语音，请继续说话');

        // 👇 关键：2秒后自动开始下一轮录音（保持连续对话）
        setTimeout(() => {
          if (isRecordingModel) {
            // startRecordingForContinue();
          }
        }, 500);
      }
    }, 3000);
  }, []);

  // ==================== 关键修复：独立的发送消息函数（接收参数） ====================
  const handleSendMessageWithContent = useCallback(async (messageContent) => {
    if (!messageContent || isLoading) return;

    // 先停止录音（不关闭弹窗）
    stopRecordingOnly();

    let currentSessionId = sessionId;
    if (!currentSessionId) {
      currentSessionId = generateRandomString(20);
      setSessionId(currentSessionId);
    }

    setIsLoading(true);
    setIsAiRecording(true);

    // ==================== 修改：添加到主消息列表和语音消息列表 ====================
    const userMsg = {
      id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      type: 'user',
      content: messageContent,
      time: getCurrentTime(),
      isError: false
    };

    // 添加到主消息列表（后台记录）
    setMessages(prev => [...prev, userMsg]);
    // 添加到语音弹窗的消息列表（展示用）
    setVoiceMessages(prev => [...prev, userMsg]);

    const newHistoryItem = { role: 'user', content: messageContent, timestamp: Date.now() };
    setChatHistory(prev => {
      const updated = [...prev, newHistoryItem];
      return updated.length > CONFIG.maxHistory ? updated.slice(-CONFIG.maxHistory) : updated;
    });

    try {
      const endpoint = currentModel === 'process' ? CONFIG.endpoints.process : CONFIG.endpoints.chat;
      const requestData = {
        message: messageContent,
        modelType: currentModel,
        sUserId,
        sUserType,
        sessionId: currentSessionId
      };

      const response = await fetch(`${CONFIG.backendUrl}${endpoint}`, {
        method: 'POST',
        headers: CONFIG.headers,
        body: JSON.stringify(requestData)
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();

      if (data.data) {
        const aiMsg = {
          id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
          type: 'ai',
          content: data.data,
          time: getCurrentTime(),
          isError: false
        };

        // 添加到主消息列表
        setMessages(prev => [...prev, aiMsg]);
        // 添加到语音弹窗的消息列表（展示用）
        setVoiceMessages(prev => [...prev, aiMsg]);

        setChatHistory(prev => {
          const updated = [...prev, { role: 'assistant', content: data.data, timestamp: Date.now() }];
          return updated.length > CONFIG.maxHistory ? updated.slice(-CONFIG.maxHistory) : updated;
        });
      }
    } catch (error) {
      console.error('请求失败:', error);
      const errorMessage = `
抱歉，请求出现错误：${error.message}

**可能的原因：**
1. Spring Boot 后端服务未启动
2. API 接口路径不正确
3. 网络连接问题

**检查步骤：**
1. 确保后端服务在端口 8099 运行
2. 检查浏览器控制台查看详细错误
3. 刷新页面重试
      `;
      const errorMsg = {
        id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        type: 'ai',
        content: errorMessage,
        time: getCurrentTime(),
        isError: true
      };

      setMessages(prev => [...prev, errorMsg]);
      setVoiceMessages(prev => [...prev, errorMsg]);
    } finally {
      setIsLoading(false);
      // setIsAiRecording(false);
      // ==================== 关键：不关闭 isRecordingModel，只清空输入准备下一轮 ====================
      setInputValue('');
      inputValueRef.current = '';
      // 重新开始录音，实现连续对话
      setTimeout(() => {
        if (isRecordingModel) {
          // startRecordingForContinue();
        }
      }, 500);
    }
  }, [sessionId, currentModel, sUserId, sUserType, isLoading, isRecordingModel]);

  // ==================== 连续对话的录音启动（不重复显示弹窗） ====================
  const startRecordingForContinue = async () => {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      Toast.show('浏览器不支持麦克风');
      return;
    }

    try {
      // 重置输入值
      setInputValue('');
      inputValueRef.current = '';

      if (!isWsConnected || !wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        connectWebSocket();
        await new Promise(resolve => setTimeout(resolve, 1000));
      }

      if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        Toast.show('语音服务未连接');
        return;
      }

      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
      inputNodeRef.current = audioContextRef.current.createMediaStreamSource(stream);
      scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(2048, 1, 1);

      scriptProcessorRef.current.onaudioprocess = (event) => {
        if (!isRecordingRef.current) return;
        const inputData = event.inputBuffer.getChannelData(0);
        const resampledData = resampleAudio(inputData, audioContextRef.current.sampleRate, CONFIG.sampleRate);
        const pcmData = float32ToInt16(resampledData);
        if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
          wsRef.current.send(pcmData);
        }
      };

      inputNodeRef.current.connect(scriptProcessorRef.current);
      scriptProcessorRef.current.connect(audioContextRef.current.destination);

      // 关键：重置标志
      wsRef.current.hasReceivedSpeech = false;

      // 启动首次静默检测
      silenceTimeoutRef.current = setTimeout(() => {
        console.log('2秒内未检测到语音，自动处理（连续对话）');
        const latestInput = inputValueRef.current.trim();
        console.log("🚀 ～ 当前输入值:", latestInput);

        if (latestInput) {
          handleSendMessageWithContent(latestInput);
        } else {
          stopRecordingOnly();
          Toast.show('请继续说话...');

          // 👇 自动开始下一轮录音
          setTimeout(() => {
            if (isRecordingModel) {
              // startRecordingForContinue();
            }
          }, 500);
        }
      }, 2000);

      // 更新录音状态
      isRecordingRef.current = true;
      setIsRecording(true);
      setIsVoiceMode(true);
      setRecordingDuration(0);

      recordingTimerRef.current = setInterval(() => {
        setRecordingDuration(prev => prev + 1);
      }, 1000);

    } catch (e) {
      console.error("录音启动失败:", e);
      Toast.show('录音启动失败：' + (e.message || '未知错误'));
      isRecordingRef.current = false;
      setIsRecording(false);
    }
  };
  useEffect(() => {
    // 确保在语音模式下才滚动
    if (isRecordingModel) {
      // 使用微任务或小延迟确保 DOM 已更新
      setTimeout(scrollToPhoneBottom, 50);
    }
  }, [voiceMessages, inputValue, isLoading, isRecordingModel]);
  // ==================== 关键修复：仅停止录音（不发送消息，不关闭弹窗） ====================
  const stopRecordingOnly = useCallback(() => {
    console.log("仅停止录音");

    // 清理静默超时
    if (silenceTimeoutRef.current) {
      clearTimeout(silenceTimeoutRef.current);
      silenceTimeoutRef.current = null;
    }

    isRecordingRef.current = false;
    setIsRecording(false);
    setIsVoiceMode(false);
    setIsFlushing(true);

    if (recordingTimerRef.current) {
      clearInterval(recordingTimerRef.current);
      recordingTimerRef.current = null;
    }

    if (inputNodeRef.current) {
      inputNodeRef.current.disconnect();
      inputNodeRef.current = null;
    }
    if (scriptProcessorRef.current) {
      scriptProcessorRef.current.disconnect();
      scriptProcessorRef.current = null;
    }
    if (audioContextRef.current) {
      audioContextRef.current.close();
      audioContextRef.current = null;
    }

    // 发送刷新指令获取最终结果
    sendCommand("flush");
  }, [sendCommand]);

  // 断开WebSocket
  const disconnectWebSocket = useCallback(() => {
    if (wsRef.current) {
      wsRef.current.close();
      wsRef.current = null;
    }
    setIsWsConnected(false);
  }, []);

  // 发送指令
  const sendCommand = useCallback((action) => {
    if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
      return;
    }
    const cmd = JSON.stringify({ action });
    wsRef.current.send(cmd);
  }, []);

  // Float32 转 Int16 PCM
  const float32ToInt16 = (float32Array) => {
    const int16Array = new Int16Array(float32Array.length);
    for (let i = 0; i < float32Array.length; i++) {
      let s = Math.max(-1, Math.min(1, float32Array[i]));
      int16Array[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
    }
    return new Uint8Array(int16Array.buffer);
  };

  // 音频重采样
  const resampleAudio = (data, originalRate, targetRate) => {
    if (originalRate === targetRate) return data;
    const ratio = targetRate / originalRate;
    const newLength = Math.round(data.length * ratio);
    const result = new Float32Array(newLength);
    for (let i = 0; i < newLength; i++) {
      result[i] = data[Math.round(i / ratio)] || 0;
    }
    return result;
  };

  // 开始录音（首次打开弹窗）
  const startRecording = async () => {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      Toast.show('浏览器不支持麦克风');
      return;
    }

    try {
      // 清空语音消息列表（新会话开始）
      setVoiceMessages([]);
      // 重置输入值
      setInputValue('');
      inputValueRef.current = '';

      if (!isWsConnected) {
        connectWebSocket();
        await new Promise(resolve => setTimeout(resolve, 1000));
      }

      if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        Toast.show('语音服务未连接');
        return;
      }

      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
      inputNodeRef.current = audioContextRef.current.createMediaStreamSource(stream);
      scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(2048, 1, 1);

      scriptProcessorRef.current.onaudioprocess = (event) => {
        if (!isRecordingRef.current) return;
        const inputData = event.inputBuffer.getChannelData(0);
        const resampledData = resampleAudio(inputData, audioContextRef.current.sampleRate, CONFIG.sampleRate);
        const pcmData = float32ToInt16(resampledData);
        if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
          wsRef.current.send(pcmData);
        }
      };

      inputNodeRef.current.connect(scriptProcessorRef.current);
      scriptProcessorRef.current.connect(audioContextRef.current.destination);

      // 关键：重置标志
      wsRef.current.hasReceivedSpeech = false;

      // ==================== 关键修复：启动首次静默检测 ====================
      silenceTimeoutRef.current = setTimeout(() => {
        console.log('2秒内未检测到语音，自动发送并停止录音');
        const latestInput = inputValueRef.current.trim();
        console.log("🚀 ~ 当前输入值:", latestInput);

        if (latestInput) {
          handleSendMessageWithContent(latestInput);
        } else {
          stopRecordingOnly();
          // setIsRecordingModel(false); // 没有内容时关闭弹窗
          Toast.show('未检测到语音输入');
        }
      }, 3000);

      // 更新录音状态
      isRecordingRef.current = true;
      setIsRecording(true);
      setIsVoiceMode(true);
      setRecordingDuration(0);

      recordingTimerRef.current = setInterval(() => {
        setRecordingDuration(prev => prev + 1);
      }, 1000);

    } catch (e) {
      console.error("录音启动失败:", e);
      Toast.show('录音启动失败：' + (e.message || '未知错误'));
      isRecordingRef.current = false;
      setIsRecording(false);
    }
  };
  // 用于打断/连续对话，不清空 voiceMessages
  const startRecordingWithoutClear = async () => {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      Toast.show('浏览器不支持麦克风');
      return;
    }

    try {
      // ❌ 不清空 voiceMessages！
      // 重置输入值（但保留历史语音消息）
      setInputValue('');
      inputValueRef.current = '';

      if (!isWsConnected || !wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        connectWebSocket();
        await new Promise(resolve => setTimeout(resolve, 1000));
      }

      if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
        Toast.show('语音服务未连接');
        return;
      }

      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioContextRef.current = new (window.AudioContext || window.webkitAudioContext)();
      inputNodeRef.current = audioContextRef.current.createMediaStreamSource(stream);
      scriptProcessorRef.current = audioContextRef.current.createScriptProcessor(2048, 1, 1);

      scriptProcessorRef.current.onaudioprocess = (event) => {
        if (!isRecordingRef.current) return;
        const inputData = event.inputBuffer.getChannelData(0);
        const resampledData = resampleAudio(inputData, audioContextRef.current.sampleRate, CONFIG.sampleRate);
        const pcmData = float32ToInt16(resampledData);
        if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
          wsRef.current.send(pcmData);
        }
      };

      inputNodeRef.current.connect(scriptProcessorRef.current);
      scriptProcessorRef.current.connect(audioContextRef.current.destination);

      wsRef.current.hasReceivedSpeech = false;

      // 静默检测（可复用）
      silenceTimeoutRef.current = setTimeout(() => {
        const latestInput = inputValueRef.current.trim();
        if (latestInput) {
          handleSendMessageWithContent(latestInput);
        } else {
          stopRecordingOnly();
          setIsAiRecording(true)
          // Toast.show('请继续说话...');
          // startRecordingForContinue()
          // 可选：自动重试
        }
      }, 3000);

      isRecordingRef.current = true;
      setIsRecording(true);
      setIsVoiceMode(true);
      setRecordingDuration(0);

      recordingTimerRef.current = setInterval(() => {
        setRecordingDuration(prev => prev + 1);
      }, 1000);

    } catch (e) {
      console.error("录音启动失败:", e);
      Toast.show('录音启动失败：' + (e.message || '未知错误'));
      isRecordingRef.current = false;
      setIsRecording(false);
    }
  };
  // 停止录音并关闭弹窗（手动挂断）
  const stopRecordingAndClose = useCallback(() => {
    console.log("停止录音并关闭弹窗");

    // 清理静默超时
    if (silenceTimeoutRef.current) {
      clearTimeout(silenceTimeoutRef.current);
      silenceTimeoutRef.current = null;
    }

    isRecordingRef.current = false;
    setIsRecording(false);
    setIsVoiceMode(false);
    setIsFlushing(true);

    if (recordingTimerRef.current) {
      clearInterval(recordingTimerRef.current);
      recordingTimerRef.current = null;
    }

    if (inputNodeRef.current) {
      inputNodeRef.current.disconnect();
      inputNodeRef.current = null;
    }
    if (scriptProcessorRef.current) {
      scriptProcessorRef.current.disconnect();
      scriptProcessorRef.current = null;
    }
    if (audioContextRef.current) {
      audioContextRef.current.close();
      audioContextRef.current = null;
    }

    sendCommand("flush");

    // 关闭弹窗并清空
    // setIsRecordingModel(false);
    setVoiceMessages([]);
    setInputValue('');
    inputValueRef.current = '';
  }, [sendCommand]);

  // 切换录音状态（点击按钮）
  const toggleRecording = useCallback(() => {
    if (isRecordingRef.current) {
      // 正在录音，停止（手动停止也触发发送）
      const latestInput = inputValueRef.current.trim();
      if (latestInput) {
        handleSendMessageWithContent(latestInput);
      } else {
        stopRecordingAndClose();
      }
    } else {
      // 未录音，开始
      startRecording();
    }
  }, [stopRecordingAndClose, handleSendMessageWithContent]);

  // 取消录音并清空
  const cancelRecording = useCallback(() => {
    if (isRecordingRef.current) {
      stopRecordingOnly();
    }
    setInputValue('');
    inputValueRef.current = '';
    setIsVoiceMode(false);
    setIsRecordingModel(false);
    setVoiceMessages([]);
  }, [stopRecordingOnly]);

  // 格式化录音时长
  const formatDuration = (seconds) => {
    const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
    const secs = (seconds % 60).toString().padStart(2, '0');
    return `${mins}:${secs}`;
  };

  // ==================== 初始化 ====================
  useEffect(() => {
    setMessages([
      {
        id: 'welcome',
        type: 'ai',
        content: '',
        time: getCurrentTime(),
        isWelcome: true
      }
    ]);

    const initSession = async () => {
      try {
        const initUrl = `${CONFIG.backendUrl}/api/v1/chat/init?sUserId=${sUserId}&sUserType=${sUserType}`;
        const response = await fetch(initUrl, {
          method: 'POST',
          headers: CONFIG.headers,
          body: JSON.stringify({})
        });
        const data = await response.json();
        if (data.data) {
          setWelcomeContent(data.data);
          setMessages(prev => prev.map(msg =>
            msg.id === 'welcome' ? { ...msg, content: data.data } : msg
          ));
        }
      } catch (error) {
        console.error('初始化失败:', error);
      }
    };

    initSession();
    inputRef.current?.focus();

    const handleKeyDown = (e) => {
      if (e.ctrlKey && e.key === 'Enter') {
        handleSendMessage();
      }
      if (e.key === 'Escape') {
        setInputValue('');
        inputValueRef.current = '';
        if (isRecordingRef.current) {
          stopRecordingAndClose();
        }
      }
    };

    document.addEventListener('keydown', handleKeyDown);

    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      disconnectWebSocket();
      if (recordingTimerRef.current) {
        clearInterval(recordingTimerRef.current);
      }
      if (silenceTimeoutRef.current) {
        clearTimeout(silenceTimeoutRef.current);
      }
    };
  }, []);

  useEffect(() => {
    scrollToBottom();
  }, [messages, isLoading, voiceMessages]);

  // ==================== 消息处理 ====================
  const addMessage = (content, type, isError = false) => {
    const newMessage = {
      id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      type,
      content,
      time: getCurrentTime(),
      isError
    };
    setMessages(prev => [...prev, newMessage]);
    return newMessage.id;
  };

  // 原有的 handleSendMessage 保留给手动输入使用
  const handleSendMessage = async () => {
    const message = inputValue.trim();
    console.log("🚀 ~ handleSendMessage ~ message:", message);

    if (!message || isLoading) return;

    let currentSessionId = sessionId;
    if (!currentSessionId) {
      currentSessionId = generateRandomString(20);
      setSessionId(currentSessionId);
    }

    setInputValue('');
    inputValueRef.current = '';
    setIsLoading(true);

    addMessage(message, 'user');

    const newHistoryItem = { role: 'user', content: message, timestamp: Date.now() };
    setChatHistory(prev => {
      const updated = [...prev, newHistoryItem];
      return updated.length > CONFIG.maxHistory ? updated.slice(-CONFIG.maxHistory) : updated;
    });

    try {
      const endpoint = currentModel === 'process' ? CONFIG.endpoints.process : CONFIG.endpoints.chat;
      const requestData = {
        message,
        modelType: currentModel,
        sUserId,
        sUserType,
        sessionId: currentSessionId
      };

      const response = await fetch(`${CONFIG.backendUrl}${endpoint}`, {
        method: 'POST',
        headers: CONFIG.headers,
        body: JSON.stringify(requestData)
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();

      if (data.data) {
        addMessage(data.data, 'ai');
        setChatHistory(prev => {
          const updated = [...prev, { role: 'assistant', content: data.data, timestamp: Date.now() }];
          return updated.length > CONFIG.maxHistory ? updated.slice(-CONFIG.maxHistory) : updated;
        });
      }
    } catch (error) {
      console.error('请求失败:', error);
      const errorMessage = `
抱歉，请求出现错误：${error.message}

**可能的原因：**
1. Spring Boot 后端服务未启动
2. API 接口路径不正确
3. 网络连接问题

**检查步骤：**
1. 确保后端服务在端口 8099 运行
2. 检查浏览器控制台查看详细错误
3. 刷新页面重试
      `;
      addMessage(errorMessage, 'ai', true);
    } finally {
      setIsLoading(false);
      inputRef.current?.focus();
    }
  };

  const handleClearChat = () => {
    if (window.confirm('确定要清空当前对话吗？')) {
      setMessages([
        {
          id: 'cleared',
          type: 'ai',
          content: '对话已清空，请开始新的对话。',
          time: getCurrentTime(),
        }
      ]);
      setChatHistory([]);
      setSessionId('');
      setInputValue('');
      inputValueRef.current = '';
      if (isRecordingRef.current) {
        stopRecordingAndClose();
      }
    }
  };

  const handleCopyMessage = (content) => {
    navigator.clipboard.writeText(content).then(() => {
      alert('已复制到剪贴板');
    });
  };

  const handleRegenerateMessage = (messageId, content) => {
    setChatHistory(prev => prev.filter(item =>
      !(item.role === 'assistant' && item.content === content)
    ));

    setMessages(prev => prev.filter(msg => msg.id !== messageId));

    setInputValue(content);
    inputValueRef.current = content;
    setTimeout(() => handleSendMessage(), 100);
  };

  const handleModelChange = (e) => {
    setCurrentModel(e.target.value);
  };

  // ==================== 渲染消息组件（复用） ====================
  const renderMessage = (msg) => (
    <div
      key={msg.id}
      className={`message ${msg.type}-message`}
    >
      <div className={`message-bubble ${msg.type}-bubble`}>
        <div className="message-content">
          {msg.type === 'ai' ? (
            <ReactMarkdown
              remarkPlugins={[remarkGfm]}
              components={{
                code: ({ node, inline, className, children, ...props }) => (
                  inline ? (
                    <code className="inline-code" {...props}>
                      {children}
                    </code>
                  ) : (
                    <pre className="code-block">
                      <code {...props}>{children}</code>
                    </pre>
                  )
                )
              }}
            >
              {msg.content}
            </ReactMarkdown>
          ) : (
            msg.content
          )}
        </div>
        <div className="message-meta">
          <span className="message-time">{msg.time}</span>
          {msg.type === 'ai' && !msg.isWelcome && (
            <div className="message-actions">
              <button
                className="action-btn"
                onClick={() => handleCopyMessage(msg.content)}
              >
                复制
              </button>
              <button
                className="action-btn"
                onClick={() => handleRegenerateMessage(msg.id, msg.content)}
              >
                重新生成
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
  const scrollToPhoneBottom = () => {
    if (phoneContentRef.current) {
      phoneContentRef.current.scrollTop = phoneContentRef.current.scrollHeight;
    }
  };
  // ==================== 渲染 ====================
  return (
    <div className="ai-chat-container">
      {/* 头部 */}
      <Button
        className="model-Button"
        onClick={handleClearChat}
      >
        清空对话
      </Button>

      {/* 主体 */}
      <div className="chat-body">
        <div className="chat-main">
          {/* 消息区域 */}
          <div className="messages-container">
            {messages.map(renderMessage)}

            {/* 打字机效果 */}
            {isLoading && (
              <div className="message ai-message">
                <div className="typing-indicator">
                  <div className="typing-dot"></div>
                  <div className="typing-dot" style={{ animationDelay: '0.2s' }}></div>
                  <div className="typing-dot" style={{ animationDelay: '0.4s' }}></div>
                  <span className="typing-text">正在思考...</span>
                </div>
              </div>
            )}

            <div ref={messagesEndRef} className="bottom-spacer" />
          </div>

          {/* 输入区域 */}
          <div className="input-section">
            <div className="input-wrapper">
              <input
                ref={inputRef}
                type="text"
                className="message-input"
                placeholder={isRecording ? "正在听您说话..." : "输入您的问题..."}
                value={inputValue}
                onChange={(e) => {
                  if (!isRecording) {
                    setInputValue(e.target.value);
                    inputValueRef.current = e.target.value;
                  }
                }}
                onKeyPress={(e) => {
                  if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    handleSendMessage();
                  }
                }}
                disabled={isLoading}
                readOnly={isRecording}
              />
              <PhoneFill className='input-icon' onClick={() => {
                setIsRecordingModel(true)
                startRecording()
              }} />
              <LocationOutline className='input-icon' onClick={handleSendMessage}
                disabled={isLoading || isRecording} />
            </div>
          </div>
        </div>
      </div>

      {/* ==================== 语音对话弹窗 ==================== */}
      {isRecordingModel && (
        <div className='phone-model'>
          <div className='phone-zhezhao'></div>

          {/* 消息展示区域 - 展示 voiceMessages 中的对话 */}
          <div className='phone-content' ref={phoneContentRef}>
            {voiceMessages.map(renderMessage)}

            {/* 当前正在输入的语音转文字（实时显示） */}
            {inputValue.trim() && isRecording && (
              <div className="message user-message">
                <div className="message-bubble user-bubble">
                  <div className="message-content">
                    {inputValue}
                  </div>
                  <div className="message-meta">
                    <span className="message-time">{getCurrentTime()}</span>
                    <span style={{ fontSize: '12px', color: '#999', marginLeft: '8px' }}>
                      (识别中...)
                    </span>
                  </div>
                </div>
              </div>
            )}

            {/* AI 思考中效果 */}
            {isLoading && (
              <div className="message ai-message">
                <div className="typing-indicator">
                  <div className="typing-dot"></div>
                  <div className="typing-dot" style={{ animationDelay: '0.2s' }}></div>
                  <div className="typing-dot" style={{ animationDelay: '0.4s' }}></div>
                  <span className="typing-text">AI 正在思考...</span>
                </div>
              </div>
            )}

            <div ref={messagesEndRef} style={{ height: '20px' }} />
          </div>

          {/* 录音状态指示器 */}
          {isRecording && (
            <div className="voice-mode-indicator">
              <div className="voice-wave">
                <span></span>
                <span></span>
                <span></span>
                <span></span>
                <span></span>
              </div>
              <span className="voice-text">
                正在录音 {formatDuration(recordingDuration)}
              </span>
            </div>
          )}

          {/* AI 说话时的打断按钮 */}
          {isAiRecording && (
            <button
              className="voice-cancel-btn"
              onClick={() => {
                setIsAiRecording(false);
                setIsLoading(false);
                startRecordingWithoutClear()
                // startRecordingForContinue();
              }}
            >
              打断
            </button>
          )}

          {/* 挂断按钮 */}
          <div className='phone-phone'>
            <PhoneFill
              color='red'
              onClick={() => {
                stopRecordingAndClose();
                setIsRecordingModel(false)
                setIsAiRecording(false)
              }}
            />
          </div>
        </div>
      )}
    </div>
  );
};

export default ChatInterface;