<template>
  <view class="flex flex-col h-screen">
    <!-- 顶部自定义导航栏 -->
    <view class="header" :style="{ paddingTop: statusBarHeight + 'px' }">
      <ChatTopNavBar ref="topNavBarRef" :mainPageDataModel="mainPageDataModel" />
    </view>

    <!-- 消息列表（可滚动区域） -->
    <scroll-view class="main flex-full overflow-hidden scroll-y" scroll-y :scroll-top="scrollTop"
      :scroll-with-animation="true" @scroll="handleScroll" @scrolltolower="handleScrollToLower">
      <!-- welcome栏 -->
      <ChatTopWelcome ref="welcomeRef" :mainPageDataModel="mainPageDataModel" />
      <NoticeMessage></NoticeMessage>

      <view class="area-msg-list-content" v-for="item in chatMsgList" :key="item.msgId" :id="item.msgId">
        <template v-if="item.msgType === MessageRole.AI">
          <ChatCardAI class="flex flex-justify-start" :key="`ai-${item.msgId}-${item.msg ? item.msg.length : 0}`"
            :text="item.finish && item.componentName ? '' : item.msg || ''" :isLoading="item.isLoading">
            <template #content v-if="item.toolCall || item.componentName">
              <AnswerComponent v-if="
                item.componentName === CompName.longTextCard
              " :answer-text="item.msg" :title="item.title" />

              <QuickBookingComponent v-if="
                item.toolCall && item.toolCall.componentName === CompName.quickBookingCard
              " />
              <DiscoveryCardComponent v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.discoveryCard
              " />
              <CreateServiceOrder v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.callServiceCard
              " :toolCall="item.toolCall" />
              <OpenMapComponent v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.openMapCard
              " />
              <Feedback v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.feedbackCard
              " :toolCall="item.toolCall" />
              <DetailCardCompontent v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.pictureAndCommodityCard
              " :toolCall="item.toolCall" />
              <AddCarCrad v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.enterLicensePlateCard
              " :toolCall="item.toolCall" />
              <SurveyQuestionnaire v-else-if="
                item.toolCall && item.toolCall.componentName === CompName.callSurveyQuestionnaire
              " :toolCall="item.toolCall" />
            </template>

            <template #footer>
              <!-- 这个是底部 -->
              <AttachListComponent v-if="item.question" :question="item.question" />
            </template>
          </ChatCardAI>
        </template>

        <template v-else-if="item.msgType === MessageRole.ME">
          <ChatCardMine class="flex flex-justify-end" :text="item.msg" />
        </template>

        <template v-else>
          <ChatCardOther class="flex flex-justify-center" :text="item.msg">
            <ActivityListComponent v-if="
              mainPageDataModel.activityList &&
              mainPageDataModel.activityList.length > 0
            " :activityList="mainPageDataModel.activityList" />

            <RecommendPostsComponent v-if="
              mainPageDataModel.recommendTheme &&
              mainPageDataModel.recommendTheme.length > 0
            " :recommendThemeList="mainPageDataModel.recommendTheme" />
          </ChatCardOther>
        </template>
      </view>
    </scroll-view>

    <!-- 输入框区域 -->
    <view class="pb-safe-area">
      <ChatQuickAccess />
      <ChatInputArea ref="inputAreaRef" v-model="inputMessage" :holdKeyboard="holdKeyboard"
        :is-session-active="isSessionActive" :stop-request="stopRequest" @send="sendMessageAction"
        @noHideKeyboard="handleNoHideKeyboard" @keyboardShow="handleKeyboardShow" @keyboardHide="handleKeyboardHide" />
    </view>
  </view>
</template>

<script setup>
import { onMounted, nextTick, onUnmounted, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import {
  SCROLL_TO_BOTTOM,
  SEND_MESSAGE_CONTENT_TEXT,
  SEND_MESSAGE_COMMAND_TYPE,
  NOTICE_EVENT_LOGOUT,
  NOTICE_EVENT_LOGIN_SUCCESS,
} from "@/constant/constant";
import { MessageRole, CompName } from "@/model/ChatModel";
import ChatTopWelcome from "../ChatTopWelcome/index.vue";
import NoticeMessage from "../NoticeMessage/index.vue";
import ChatTopNavBar from "../ChatTopNavBar/index.vue";
import ChatCardAI from "../ChatCardAi/index.vue";
import ChatCardMine from "../ChatCardMine/index.vue";
import ChatCardOther from "../ChatCardOther/index.vue";
import ChatQuickAccess from "../ChatQuickAccess/index.vue";
import ChatInputArea from "../ChatInputArea/index.vue";
import QuickBookingComponent from "../../module/QuickBookingComponent/index.vue";
import DiscoveryCardComponent from "../../module/DiscoveryCardComponent/index.vue";
import ActivityListComponent from "../../module/ActivityListComponent/index.vue";
import RecommendPostsComponent from "../../module/RecommendPostsComponent/index.vue";
import AttachListComponent from "../../module/AttachListComponent/index.vue";
import DetailCardCompontent from "../../module/DetailCardCompontent/index.vue";
import OpenMapComponent from "../../module/OpenMapComponent/index.vue";
import AnswerComponent from "../../module/AnswerComponent/index.vue";
import CreateServiceOrder from "@/components/CreateServiceOrder/index.vue";
import Feedback from "@/components/Feedback/index.vue";
import AddCarCrad from "@/components/AddCarCrad/index.vue";
import SurveyQuestionnaire from "@/components/SurveyQuestionnaire/index.vue";
import { mainPageData } from "@/request/api/MainPageDataApi";
import {
  conversationMsgList,
  recentConversation,
} from "@/request/api/ConversationApi";
import WebSocketManager from "@/utils/WebSocketManager";
import { ThrottleUtils, IdUtils } from "@/utils";
import { checkToken } from "@/hooks/useGoLogin";
import { useAppStore } from "@/store";
import { getAccessToken } from "@/constant/token";

const appStore = useAppStore();
/// 导航栏相关
const statusBarHeight = ref(20);
/// 输入框组件引用
const inputAreaRef = ref(null);
const topNavBarRef = ref();
const welcomeRef = ref();

const holdKeyboardTimer = ref(null);
/// focus时，点击页面的时候不收起键盘
const holdKeyboard = ref(false);
/// 是否在键盘弹出，点击界面时关闭键盘
const holdKeyboardFlag = ref(true);
/// 是否显示键盘
const isKeyboardShow = ref(false);

///（控制滚动位置）
const scrollTop = ref(99999);

/// 会话列表
const chatMsgList = ref([]);
/// 输入口的输入消息
const inputMessage = ref("");

/// agentId 首页接口中获取
const agentId = ref("1");
/// 会话ID 历史数据接口中获取
const conversationId = ref("");
/// 首页的数据
const mainPageDataModel = ref({});

// 会话进行中标志
const isSessionActive = ref(false);
/// 指令
let messageCommonType = "";

// WebSocket 相关
let webSocketManager = null;
/// 使用统一的连接状态判断函数，避免状态不同步
const isWsConnected = () => !!(webSocketManager && typeof webSocketManager.isConnected === "function" && webSocketManager.isConnected());

// pendingMap: messageId -> msgIndex
const pendingMap = new Map();
// pendingTimeouts: messageId -> timeoutId
const pendingTimeouts = new Map();
// 超时时间（ms）
const MESSAGE_TIMEOUT = 30000;

// 防止并发初始化 websocket
let isInitializing = false;
let pendingInitPromise = null;
// sleep helper
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));

// 当前会话的消息ID，用于保持发送和终止的messageId一致
let currentSessionMessageId = null;

/// =============事件函数↓================
const handleTouchEnd = () => {
  clearTimeout(holdKeyboardTimer.value);
  holdKeyboardTimer.value = setTimeout(() => {
    // 键盘弹出时点击界面则关闭键盘
    if (holdKeyboardFlag.value && isKeyboardShow.value) {
      uni.hideKeyboard();
    }
    holdKeyboardFlag.value = true;
  }, 100);
};

// 点击输入框、发送按钮时，不收键盘
const handleNoHideKeyboard = () => (holdKeyboardFlag.value = false);

// 键盘弹起事件
const handleKeyboardShow = () => {
  isKeyboardShow.value = true;
  holdKeyboard.value = true;
  // 键盘弹起时调整聊天内容的底部边距并滚动到底部
  setTimeout(() => {
    scrollToBottom();
  }, 150);
};

// 键盘收起事件
const handleKeyboardHide = () => {
  isKeyboardShow.value = false;
  holdKeyboard.value = false;
};

// 处理用户滚动事件
const welcomeHeight = ref(0);
const handleScroll = ThrottleUtils.createThrottle(({ detail }) => {
  topNavBarRef.value.show = parseInt(detail.scrollTop) > welcomeHeight.value;
}, 50);

// 处理滚动到底部事件
const handleScrollToLower = () => { };

// 滚动到底部 - 优化版本，确保打字机效果始终可见
const scrollToBottom = () => {
  nextTick(() => {
    // 使用更大的值确保滚动到真正的底部
    scrollTop.value = 99999;
    // 强制触发滚动更新，增加延迟确保DOM更新完成
    setTimeout(() => {
      scrollTop.value = scrollTop.value + Math.random();
    }, 10);
  });
};

// 延时滚动
const setTimeoutScrollToBottom = () => setTimeout(() => scrollToBottom(), 100);

// 发送普通消息
const handleReplyText = (text) => {
  // 重置消息状态，准备接收新的AI回复
  resetMessageState();
  sendMessage(text);
  setTimeoutScrollToBottom();
};

// 是发送指令消息
const handleReplyInstruct = async (item) => {
  await checkToken();

  messageCommonType = item.type;
  // 重置消息状态，准备接收新的AI回复
  resetMessageState();
  sendMessage(item.title, true);
  setTimeoutScrollToBottom();
};

//  输入区的发送消息事件
const sendMessageAction = (inputText) => {
  console.log("输入消息:", inputText);
  if (!inputText.trim()) return;
  handleNoHideKeyboard();

  // 重置消息状态，准备接收新的AI回复
  resetMessageState();

  sendMessage(inputText);
  // 发送消息后保持键盘状态
  if (holdKeyboard.value && inputAreaRef.value) {
    setTimeout(() => {
      inputAreaRef.value.focusInput();
    }, 100);
  }

  setTimeoutScrollToBottom();
};

/// 添加通知
const addNoticeListener = () => {
  uni.$on(NOTICE_EVENT_LOGIN_SUCCESS, () => {
    if (!isWsConnected()) {
      initHandler();
    }
  });

  uni.$on(NOTICE_EVENT_LOGOUT, () => {
    resetConfig();
  });

  uni.$on(SCROLL_TO_BOTTOM, () => {
    setTimeout(() => {
      scrollToBottom();
    }, 200);
  });

  uni.$on(SEND_MESSAGE_CONTENT_TEXT, (value) => {
    console.log("SEND_MESSAGE_CONTENT_TEXT:", value);
    if (value && value.length > 0) {
      handleReplyText(value);
    }
  });

  uni.$on(SEND_MESSAGE_COMMAND_TYPE, (item) => {
    console.log("SEND_MESSAGE_COMMAND_TYPE:", item);
    if (item && item.type) {
      handleReplyInstruct(item);
    }
  });
};

/// =============生命周期函数↓================
onLoad(() => {
  uni.getSystemInfo({
    success: (res) => {
      statusBarHeight.value = res.statusBarHeight || 20;
    },
  });
});

// token存在，初始化数据
const initHandler = () => {
  console.log("initHandler");
  const token = getAccessToken();

  if (!token) return;
  loadRecentConversation();
  ///loadConversationMsgList();
  initWebSocket();
};

onMounted(() => {
  try {
    getMainPageData();
    addNoticeListener();
    // 有token时，加载最近会话、最近消息、初始化socket
    initHandler();
  } catch (error) {
    console.error("页面初始化错误:", error);
  }
});

/// =============页面配置↓================
// 获取最近一次的会话id
const loadRecentConversation = async () => {
  const res = await recentConversation();
  if (res.code === 0) {
    conversationId.value = res.data.conversationId;
  }
};

// 加载历史消息的数据
let historyCurrentPageNum = 1;
const loadConversationMsgList = async () => {
  const args = {
    pageNum: historyCurrentPageNum++,
    pageSize: 10,
    conversationId: conversationId.value,
  };
  const res = await conversationMsgList(args);
};

// 获取首页数据

const getMainPageData = async () => {
  /// 从个渠道获取如二维，没有的时候就返回首页的数据
  const sceneId = appStore.sceneId || "";
  const res = await mainPageData({ sceneId });

  if (res.code === 0) {
    initData();
    mainPageDataModel.value = res.data;
    agentId.value = res.data.agentId;
    // 数据更新后再次测量欢迎区高度
    welcomeRef.value.measureWelcomeHeight((data) => {
      console.log("🚀 ~ getMainPageData ~ data:", data);
      welcomeHeight.value = data.height;
    });
  }
  appStore.setSceneId(""); // 清空sceneId,分身二次进入展示默认的
};

/// =============对话↓================
// 初始化WebSocket
const initWebSocket = async () => {
  // 防止并发初始化
  if (isInitializing) {
    return pendingInitPromise;
  }

  isInitializing = true;
  pendingInitPromise = (async () => {
    // 清理旧实例
    if (webSocketManager) {
      try {
        webSocketManager.destroy();
      } catch (e) {
        console.warn("destroy old webSocketManager failed:", e);
      }
      webSocketManager = null;
    }

    // 使用配置的WebSocket服务器地址
    const token = getAccessToken();
    const wsUrl = `${appStore.serverConfig.wssUrl}?access_token=${token}`;

    // 初始化WebSocket管理器
    webSocketManager = new WebSocketManager({
      wsUrl: wsUrl,
      reconnectInterval: 3000, // 重连间隔
      maxReconnectAttempts: 5, // 最大重连次数
      heartbeatInterval: 30000, // 心跳间隔

      // 连接成功回调
      onOpen: (event) => {
        console.log("WebSocket连接成功");
        // 重置会话状态
        isSessionActive.value = false; // 连接成功时重置会话状态，避免影响新消息发送
      },

      // 连接断开回调
      onClose: (event) => {
        console.error("WebSocket连接断开:", event);
        // 停止当前会话
        isSessionActive.value = false;
      },

      // 错误回调
      onError: (error) => {
        console.error("WebSocket错误:", error);
        isSessionActive.value = false;
      },

      // 消息回调
      onMessage: (data) => {
        handleWebSocketMessage(data);
      },

      // 获取会话ID回调 (用于心跳检测)
      getConversationId: () => conversationId.value,

      // 获取代理ID回调 (用于心跳检测)
      getAgentId: () => agentId.value,
    });

    try {
      // 初始化连接
      await webSocketManager.connect();
      console.log("WebSocket连接初始化成功");
      return true;
    } catch (error) {
      console.error("WebSocket连接失败:", error);
      return false;
    } finally {
      isInitializing = false;
      pendingInitPromise = null;
    }
  })();

  return pendingInitPromise;
};

// 处理WebSocket消息
const handleWebSocketMessage = (data) => {
  // 验证关键字段（若服务端传回 conversationId/agentId，则校验是否属于当前会话）
  if (data.conversationId && data.conversationId !== conversationId.value) {
    console.warn("收到不属于当前会话的消息，忽略", data.conversationId);
    return;
  }
  if (data.agentId && data.agentId !== agentId.value) {
    console.warn("收到不属于当前 agent 的消息，忽略", data.agentId);
    return;
  }

  let aiMsgIndex = -1;
  if (currentSessionMessageId && pendingMap.has(currentSessionMessageId)) {
    aiMsgIndex = pendingMap.get(currentSessionMessageId);
    if (aiMsgIndex >= 0 && aiMsgIndex < chatMsgList.value.length) {
      const item = chatMsgList.value[aiMsgIndex];
      if (item && item.msgType === MessageRole.AI && 
          item.replyMessageId.length > 0 && data.replyMessageId &&
          item.replyMessageId !== data.replyMessageId) {
        // 已经存在对应的AI消息项，继续使用
        const aiMsg = {
          msgId: `msg_${chatMsgList.value.length}`,
          msgType: MessageRole.AI,
          msg: "",
          isLoading: false,
          messageId: currentSessionMessageId,
          replyMessageId: '',
          componentName: "",
          title: "",
          finish: false,
        };
        chatMsgList.value.push(aiMsg);
        aiMsgIndex = chatMsgList.value.length - 1;
      } 
    }
  } else {
    // 向后搜索最近的 AI 消息（回退逻辑）
    for (let i = chatMsgList.value.length - 1; i >= 0; i--) {
      if (chatMsgList.value[i] && chatMsgList.value[i].msgType === MessageRole.AI) {
        aiMsgIndex = i;
        break;
      }
    }
    if (aiMsgIndex === -1) {
      console.error("处理WebSocket消息时找不到对应的AI消息项");
      return;
    }
  }

  // replyMessageId
  if(data.replyMessageId) {
    chatMsgList.value[aiMsgIndex].replyMessageId = data.replyMessageId;
  }

  // 确保消息内容是字符串类型
  if (data.content && typeof data.content !== "string") {
    try {
      data.content = JSON.stringify(data.content);
    } catch (e) {
      data.content = String(data.content);
    }
  }

  // 直接拼接内容到对应 AI 消息
  if (data.content) {
    if (chatMsgList.value[aiMsgIndex].isLoading) {
      // 首次收到内容：替换“加载中”文案并取消 loading 状态（恢复原始渲染逻辑）
      chatMsgList.value[aiMsgIndex].msg = data.content;
      chatMsgList.value[aiMsgIndex].isLoading = false;
    } else {
      // 后续流式内容追加
      chatMsgList.value[aiMsgIndex].msg += data.content;
    }
    nextTick(() => scrollToBottom());
  }

  // 处理完成状态
  if (data.finish) {
    chatMsgList.value[aiMsgIndex].finish = true;
    const msg = chatMsgList.value[aiMsgIndex].msg;
    if (!msg || chatMsgList.value[aiMsgIndex].isLoading) {
      // 如果服务器返回了 componentName 或 toolCall，应保留空消息以供组件渲染；否则显示错误占位
      if (data.toolCall || data.componentName) {
        chatMsgList.value[aiMsgIndex].msg = "";
      } else {
        chatMsgList.value[aiMsgIndex].msg = "未获取到内容，请重试";
      }
      chatMsgList.value[aiMsgIndex].isLoading = false;
    }

    // 处理组件调用
    if (data.componentName) {
      chatMsgList.value[aiMsgIndex].title = data.content;
      chatMsgList.value[aiMsgIndex].componentName = data.componentName;
    }

    // 处理toolCall
    if (data.toolCall) {
      chatMsgList.value[aiMsgIndex].toolCall = data.toolCall;
    }

    // 处理question
    if (data.question && data.question.length > 0) {
      chatMsgList.value[aiMsgIndex].question = data.question;
    }

    // 清理 pendingMap / timeout
    const ownedMessageId = chatMsgList.value[aiMsgIndex].messageId || msgId;
    if (ownedMessageId) {
      if (pendingTimeouts.has(ownedMessageId)) {
        clearTimeout(pendingTimeouts.get(ownedMessageId));
        pendingTimeouts.delete(ownedMessageId);
      }
      pendingMap.delete(ownedMessageId);
    }

    // 重置会话状态
    isSessionActive.value = false;
    // 清理当前会话的 messageId，避免保留陈旧 id
    resetMessageState();

    nextTick(() => scrollToBottom());
  }
};

// 重置消息状态
const resetMessageState = () => {
  // 重置当前会话消息ID
  currentSessionMessageId = null;
};

// 初始化数据 首次数据加载的时候
const initData = () => {
  const msg = {
    msgId: `msg_${0}`,
    msgType: MessageRole.OTHER,
    msg: "",
  };
  chatMsgList.value.push(msg);
};

// 发送消息的参数拼接
const sendMessage = async (message, isInstruct = false) => {
  console.log("发送的消息：", message);

  await checkToken();

  // 检查WebSocket连接状态，如果未连接，尝试重新连接
  if (!isWsConnected()) {
    console.log("WebSocket未连接，尝试重新连接...");
    // 显示加载提示
    uni.showLoading({
      title: "正在连接服务器...",
    });

    // 尝试重新初始化WebSocket连接
    try {
      await initWebSocket();
      // 等待短暂时间确保连接建立
      await new Promise(resolve => setTimeout(resolve, 1000));

      // 检查连接是否成功建立
      if (!isWsConnected()) {
        uni.hideLoading();
        uni.showToast({
          title: "连接服务器失败，请稍后重试",
          icon: "none",
        });
        return;
      }
      uni.hideLoading();
    } catch (error) {
      console.error("重新连接WebSocket失败:", error);
      uni.hideLoading();
      uni.showToast({
        title: "连接服务器失败，请稍后重试",
        icon: "none",
      });
      return;
    }
  }

  if (isSessionActive.value) {
    uni.showToast({
      title: "请等待当前回复完成",
      icon: "none",
    });
    return;
  }
  isSessionActive.value = true;
  const newMsg = {
    msgId: `msg_${chatMsgList.value.length}`,
    msgType: MessageRole.ME,
    msg: message,
  };
  chatMsgList.value.push(newMsg);
  inputMessage.value = "";
  // 发送消息后滚动到底部
  setTimeoutScrollToBottom();
  sendChat(message, isInstruct);
  console.log("发送的新消息：", JSON.stringify(newMsg));
};

// 通用WebSocket消息发送函数 -> 返回 Promise<boolean>
const sendWebSocketMessage = async (messageType, messageContent, options = {}) => {
  const args = {
    conversationId: conversationId.value,
    agentId: agentId.value,
    messageType: String(messageType), // 消息类型 0-对话 1-指令 2-中断停止 3-心跳检测
    messageContent: messageContent,
    messageId: options.messageId || currentSessionMessageId,
  };

  const maxRetries = typeof options.retries === 'number' ? options.retries : 3;
  const baseDelay = typeof options.baseDelay === 'number' ? options.baseDelay : 300; // ms
  const maxDelay = typeof options.maxDelay === 'number' ? options.maxDelay : 5000; // ms

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    // 确保连接
    if (!isWsConnected()) {
      if (options.tryReconnect) {
        try {
          await initWebSocket();
        } catch (e) {
          console.error('reconnect failed in sendWebSocketMessage:', e);
        }
      }
    }

    if (!isWsConnected()) {
      if (!options.silent) console.warn('WebSocket 未连接，无法发送消息', args);
      // 如果还有重试机会，进行等待后重试
      if (attempt < maxRetries) {
        const delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
        await sleep(delay);
        continue;
      }
      isSessionActive.value = false;
      return false;
    }

    try {
      const raw = webSocketManager.sendMessage(args);
      // 兼容可能返回同步布尔或 Promise 的实现
      const result = await Promise.resolve(raw);
      if (result) {
        console.log(`WebSocket消息已发送 [类型:${messageType}]:`, args);
        return true;
      }

      // 若返回 false，消息可能已经被 manager 入队并触发连接流程。
      // 在这种情况下避免立即当作失败处理，而是等待短暂时间以观察连接是否建立并由 manager 发送队列。
      console.warn('webSocketManager.sendMessage 返回 false，等待连接或队列发送...', { attempt, args });
      const waitForConnectMs = typeof options.waitForConnectMs === 'number' ? options.waitForConnectMs : 5000;
      if (webSocketManager && typeof webSocketManager.isConnected === 'function' && !webSocketManager.isConnected()) {
        const startTs = Date.now();
        while (Date.now() - startTs < waitForConnectMs) {
          await sleep(200);
          if (webSocketManager.isConnected()) {
            // 给 manager 一点时间处理队列并发送
            await sleep(150);
            console.log('检测到 manager 已连接，假定队列消息已发送', args);
            return true;
          }
        }
        console.warn('等待 manager 建连超时，进入重试逻辑', { waitForConnectMs, args });
      } else {
        console.warn('sendMessage 返回 false 但 manager 看起来已连接或不可用，继续重试', { args });
      }
    } catch (error) {
      console.error('发送WebSocket消息异常:', error, args);
    }

    // 失败且还有重试机会，等待指数退避
    if (attempt < maxRetries) {
      const delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
      await sleep(delay + Math.floor(Math.random() * 100));
      continue;
    }

    // 最后一次失败
    isSessionActive.value = false;
    return false;
  }
  // 不可达，但为了类型安全
  isSessionActive.value = false;
  return false;
};

// 发送获取AI聊天消息
const sendChat = async (message, isInstruct = false) => {
  // 检查WebSocket管理器是否存在，如果不存在，尝试重新初始化
  if (!webSocketManager) {
    console.error("WebSocket管理器不存在，尝试重新初始化...");
    initWebSocket();
    // 短暂延迟后再次检查连接状态
    setTimeout(() => {
      const connected = webSocketManager && webSocketManager.isConnected();
      isSessionActive.value = connected;
      // 更新AI消息状态
      const aiMsgIndex = chatMsgList.value.length - 1;
      if (aiMsgIndex >= 0 && chatMsgList.value[aiMsgIndex].msgType === MessageRole.AI) {
        chatMsgList.value[aiMsgIndex].msg = connected ? "" : "发送消息失败，请重试";
        chatMsgList.value[aiMsgIndex].isLoading = connected;
      }
      if (connected) {
        // 连接成功后重新发送消息
        sendChat(message, isInstruct);
      } else {
        console.error("WebSocket重新初始化失败");
      }
    }, 1000);
    return;
  }

  const messageType = isInstruct ? 1 : 0;
  const messageContent = isInstruct ? messageCommonType : message;
  // 生成 messageId 并保存到当前会话变量（stopRequest 可能使用）
  currentSessionMessageId = IdUtils.generateMessageId();

  // 插入AI消息，并在 pendingMap 中记录
  const aiMsg = {
    msgId: `msg_${chatMsgList.value.length}`,
    msgType: MessageRole.AI,
    msg: "加载中",
    isLoading: true,
    messageId: currentSessionMessageId,
    replyMessageId: '',
    componentName: "",
    title: "",
    finish: false,
  };
  chatMsgList.value.push(aiMsg);
  // 添加AI消息后滚动到底部
  setTimeoutScrollToBottom();
  const aiMsgIndex = chatMsgList.value.length - 1;

  // 记录 pendingMap
  pendingMap.set(currentSessionMessageId, aiMsgIndex);

  // 启动超时回退
  const timeoutId = setTimeout(() => {
    const idx = pendingMap.get(currentSessionMessageId);
    if (idx != null && chatMsgList.value[idx] && chatMsgList.value[idx].isLoading) {
      chatMsgList.value[idx].msg = "请求超时，请重试";
      chatMsgList.value[idx].isLoading = false;
      pendingMap.delete(currentSessionMessageId);
      pendingTimeouts.delete(currentSessionMessageId);
      isSessionActive.value = false;
      setTimeoutScrollToBottom();
    }
  }, MESSAGE_TIMEOUT);
  pendingTimeouts.set(currentSessionMessageId, timeoutId);

  // 发送消息，支持重连尝试
  const success = await sendWebSocketMessage(messageType, messageContent, { messageId: currentSessionMessageId, tryReconnect: true });
  if (!success) {
    const idx = pendingMap.get(currentSessionMessageId);
    if (idx != null && chatMsgList.value[idx]) {
      chatMsgList.value[idx].msg = "发送消息失败，请重试";
      chatMsgList.value[idx].isLoading = false;
    }
    // 清理 pending
    if (pendingTimeouts.has(currentSessionMessageId)) {
      clearTimeout(pendingTimeouts.get(currentSessionMessageId));
      pendingTimeouts.delete(currentSessionMessageId);
    }
    pendingMap.delete(currentSessionMessageId);
    isSessionActive.value = false;
  }
};

// 停止请求函数
const stopRequest = async () => {
  console.log("停止请求");

  // 发送中断消息给服务器 (messageType=2)，带上当前 messageId
  try {
    await sendWebSocketMessage(2, "stop_request", { messageId: currentSessionMessageId, silent: true });
  } catch (e) {
    console.warn("stopRequest send failed:", e);
  }

  // 直接将AI消息状态设为停止（优先使用 pendingMap 映射）
  let aiMsgIndex = -1;
  if (currentSessionMessageId && pendingMap.has(currentSessionMessageId)) {
    aiMsgIndex = pendingMap.get(currentSessionMessageId);
  } else {
    aiMsgIndex = chatMsgList.value.length - 1;
  }

  if (chatMsgList.value[aiMsgIndex] &&
    chatMsgList.value[aiMsgIndex].msgType === MessageRole.AI) {
    chatMsgList.value[aiMsgIndex].isLoading = false;
    if (chatMsgList.value[aiMsgIndex].msg &&
      chatMsgList.value[aiMsgIndex].msg.trim() &&
      !chatMsgList.value[aiMsgIndex].msg.startsWith("加载中")) {
      // 保留已显示内容
    } else {
      chatMsgList.value[aiMsgIndex].msg = "请求已停止";
    }
  }

  // 清理 pending
  if (currentSessionMessageId) {
    if (pendingTimeouts.has(currentSessionMessageId)) {
      clearTimeout(pendingTimeouts.get(currentSessionMessageId));
      pendingTimeouts.delete(currentSessionMessageId);
    }
    pendingMap.delete(currentSessionMessageId);
  }

  // 重置会话状态
  isSessionActive.value = false;
  setTimeoutScrollToBottom();
};

// 组件销毁时清理资源
onUnmounted(() => {
  uni.$off(NOTICE_EVENT_LOGIN_SUCCESS);
  uni.$off(SCROLL_TO_BOTTOM);
  uni.$off(SEND_MESSAGE_CONTENT_TEXT);
  uni.$off(SEND_MESSAGE_COMMAND_TYPE);
  uni.$off(NOTICE_EVENT_LOGOUT);

  resetConfig();
});

const resetConfig = () => {
  // 清理WebSocket连接
  if (webSocketManager) {
    webSocketManager.destroy();
    webSocketManager = null;
  }

  // 重置消息状态
  resetMessageState();
  isSessionActive.value = false;

  // 清理 pendingMap / pendingTimeouts
  try {
    for (const t of pendingTimeouts.values()) {
      clearTimeout(t);
    }
  } catch (e) {
    // ignore
  }
  pendingTimeouts.clear();
  pendingMap.clear();

  // 清理定时器
  if (holdKeyboardTimer.value) {
    clearTimeout(holdKeyboardTimer.value);
    holdKeyboardTimer.value = null;
  }
};
</script>

<style lang="scss" scoped></style>
