<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import BG from "./components/BG.vue";
import BottomArea from "./components/BottomArea.vue";
import ChatList from "./components/ChatList.vue";
import NavBarPage from "../components/NavBarPage.vue";
import PQueue from "p-queue";
import axios from "axios";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import { useRoute, useRouter } from "vue-router";
import delay from "delay";
import { fetchTaskStatus } from "./utils/api";

const route = useRoute();
const router = useRouter();
const conversationId = computed(() => route.query.taskId); // 会话ID
const round = computed(() => route.query.round); // 轮次
const scenceType = computed(() => route.query.scenceType); // 场景类型
const sessionId = ref("");
const taskStatus = ref(false)
const loading = ref(true);  //初始化进入的加载状态

const currentRate = ref(0);
const currentRound = computed(() => {
  const filteredMessages = chatList.value.filter(
    (message) =>
      message.text !== "我没有听清，麻烦在重复一下。" && message.text !== ""
  );
  return Math.floor(filteredMessages.length / 2);
});
// 当前进度百分比整数部分
const rate = computed(() => {
  return Math.floor((currentRound.value / round.value) * 100);
});

const text = computed(() => `${currentRound.value} / ${round.value}`);

// 对话记录
const chatList = ref([]);
let i = 0;
// 我 我是 我是中国人 我是中国人的英雄 我是中国人的英雄。[
const updateChatList = async (message = "", loading = true) => {
  const timer = setInterval(() => {
    i = i + 1;
    chatList.value = chatList.value.map((item, index) => {
      if (index == chatList.value.length - 1) {
        return {
          ...item,
          text: message.substring(0, i),
        };
      } else {
        return item;
      }
    });
    localStorage.setItem("chatHistory", JSON.stringify(chatList.value));
    if (i >= message.length) {
      clearInterval(timer);
    }
  }, 50);
};

// 创建一个队列实例，设置并发数为 1
const queue = new PQueue({ concurrency: 3 });
const queue1 = new PQueue({ concurrency: 1 });
const queue2 = new PQueue({ concurrency: 1 });

// 需要tts的文本队列
const messageQueue = [];

// lastStrIndex 用于记录上一个字符串的结束位置
let lastStrIndex = 0;

// 将字符串根据标点符号断句分割，并添加到messageQueue中
const splitMessage = async (str) => {
  const punctuation = ["。","，" ,"！", "？", "；", "："];

  for (let i = lastStrIndex; i < str.length; i++) {
    if (punctuation.includes(str[i])) {
      const message = str.slice(lastStrIndex, i + 1);
      console.log(message, "==========");
      playTTS(message);
      lastStrIndex = i + 1; // 更新上一个字符串的结束位置
    }
  }
};

const handleStartRecord = async () => {
  queue.clear();
  queue1.clear();
};

const generateSessionId = () => {
  // 获取当前时间戳
  const timestamp = Date.now().toString();
  // 生成一个随机数
  const randomNum = Math.floor(Math.random() * 10000);
  // 将时间戳和随机数拼接成会话ID
  const sessionId = `${timestamp}${randomNum}`;
  return sessionId;
};

// 发送消息
const handleStopRecord = (message) => {
  lastStrIndex = 0; // 重置
  chatList.value = [
    ...chatList.value,
    {
      id: Date.now(),
      type: "user",
      text: message,
      loading: false,
    },
    {
      id: Date.now(),
      type: "gpt",
      text: "",
      loading: true,
    },
  ];
  sessionId.value = generateSessionId();
  chatGpt(message);
};
// let audioQueue = [];  // 音频队列，保存按请求顺序的音频数据
// let playingQueue = []; // 用来记录当前正在播放的音频序号
// let isPlaying = false;  // 当前是否正在播放
// let orderId = 0;  // 请求顺序号

// 用来控制正在播放音频的锁定机制
let playingLock = false;  // 标识是否正在播放


let audioQueue = [];  // 音频队列，保存按请求顺序的音频数据
let playingQueue = []; // 记录已播放的音频序号
let isPlaying = false;  // 当前是否正在播放
let orderId = 0;  // 请求顺序号

// 1. 发起 TTS 请求（修改后）
const playTTS = async (ttsMessage) => {
  queue.add(async () => {
    const currentOrderId = orderId++;  // 先获取顺序号再发送请求

    try {
      const res = await axios.get(
        `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`,
        { responseType: "arraybuffer" }
      );
      
      // 即使请求失败也要保持队列连续性（新增部分）
      const audioItem = {
        orderId: currentOrderId,
        audioData: res.data || null,
        status: res.data ? 'valid' : 'invalid'
      };
      
      audioQueue.push(audioItem);
      audioQueue.sort((a, b) => a.orderId - b.orderId);  // 保持队列有序

      if (!isPlaying) await playNextAudio();
    } catch (error) {
      console.error("调用 TTS API 时出错:", error);
      // 请求失败时插入占位符保持顺序（关键修复）
      audioQueue.push({ 
        orderId: currentOrderId,
        audioData: null,
        status: 'invalid'
      });
      audioQueue.sort((a, b) => a.orderId - b.orderId);
      if (!isPlaying) await playNextAudio();
    }
  });
};

// 2. 播放下一个音频（修改后）
const playNextAudio = async () => {
  // if (audioQueue.length === 0) {
  //   isPlaying = false;
  //   console.log("所有音频播放完毕.");
  //   return;
  // }
  if (audioQueue.length === 0 && playingQueue.length > 0) {
  const maxPlayed = Math.max(...playingQueue);
  if (orderId > maxPlayed + 1) {
    console.log("仍有未完成请求，暂不重置");
  } else {
    isPlaying = false;
    // 新增：当队列完全播放完毕时重置所有状态
    audioQueue = [];
    playingQueue = [];
    orderId = 0;  // 可选：如果需要重置顺序号
    console.log("所有音频播放完毕，已重置播放队列.");
    return;
  }
  }

  const nextAudio = getNextAudioToPlay();
  if (!nextAudio) {
    console.log("等待后续音频数据...");
    return;
  }

  try {
    isPlaying = true;
    console.log(`正在播放音频，序号：${nextAudio.orderId}`);

    if (nextAudio.status === 'valid') {
      await playAudio(nextAudio.audioData);
    } else {
      console.warn(`跳过无效音频，序号：${nextAudio.orderId}`);
    }

    // 更新播放状态（优化处理）
    playingQueue = [...new Set([...playingQueue, nextAudio.orderId])].sort((a, b) => a - b);
    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);

    // 立即尝试播放下一个（优化播放流程）
    isPlaying = false;
    await playNextAudio();
  } catch (error) {
    console.error(`播放失败，序号：${nextAudio.orderId}`, error);
    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);
    isPlaying = false;
    await playNextAudio();
  }
};

// 获取下一个应该播放的音频（修改后）
const getNextAudioToPlay = () => {
  // 获取当前应该播放的最小序号
  const expectedOrderId = playingQueue.length > 0 
    ? Math.max(...playingQueue) + 1 
    : 0;

  // 查找第一个匹配的有效音频（新增有效性检查）
  const nextAudio = audioQueue.find(audio => 
    audio.orderId === expectedOrderId &&
    audio.status === 'valid'
  );

  // 如果找不到有效音频但有序号匹配的无效项，跳过该序号
  if (!nextAudio) {
    const invalidAudio = audioQueue.find(audio => 
      audio.orderId === expectedOrderId
    );
    
    if (invalidAudio) {
      console.warn(`检测到无效音频，自动跳过序号：${expectedOrderId}`);
      playingQueue.push(expectedOrderId);
      return getNextAudioToPlay(); // 递归处理
    }
  }

  return nextAudio || null;
};
// 1. 发起 TTS 请求

// const playTTS = async (ttsMessage) => {
//   queue.add(async () => {
//     const currentOrderId = orderId++;

//     try {
//       const res = await axios.get(
//         `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`,
//         { responseType: "arraybuffer" }
//       );
//       if (!res.data || res.data.byteLength === 0) {
//         console.error("音频数据无效，无法播放.");
//         return;
//       }
//       // 按顺序存入音频队列
//       audioQueue.push({ orderId: currentOrderId, audioData: res.data });

//       // 仅在没有播放时启动播放
//       if (!isPlaying) {
//         await playNextAudio();
//       }
//     } catch (error) {
//       console.error("调用 TTS API 时出错:", error);
//     }
//   });
// };
// 2. 播放下一个音频
// const playNextAudio = async () => {
//   // 如果播放队列为空，停止播放
//   if (audioQueue.length === 0) {
//     isPlaying = false;  // 播放完所有音频
//     // audioQueue = []; // 确保列表为空
//     console.log("所有音频播放完毕.");
//     return;
//   }

//   // 找到队列中最小序号的音频，确保顺序播放
//   const nextAudio = getNextAudioToPlay();
//   console.log(nextAudio,"没有找到下一个应该播放的音频，队列尚未按顺序准备好.");

//   // 如果找不到下一个应该播放的音频，表示队列还没有按顺序准备好
//   if (!nextAudio) {
//     console.log("没有找到下一个应该播放的音频，队列尚未按顺序准备好.");
//     console.log("当前音频队列:", audioQueue);  // 打印当前音频队列
//     console.log("当前已播放的序列:", playingQueue);  // 打印已经播放的音频序列
//     return;
//   }

//   // 打印正在播放的音频序号
//   console.log(`正在播放音频，序号：${nextAudio.orderId}`);

//   try {
//     isPlaying = true;  // 标记当前正在播放
//     playingLock = true;  // 锁定播放，避免新的音频插入

//     // 播放当前音频
//     await playAudio(nextAudio.audioData);

//     // 播放完成后，移除已播放的音频
//     audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);
//     playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录

//     // 输出音频播放完成的日志
//     console.log(`音频序号 ${nextAudio.orderId} 播放完成，等待播放下一个包...`);

//     // 解除锁定，等待下一个音频播放
//     playingLock = false;

//     // 使用定时器周期性检查是否可以播放下一个音频
//     const checkNextAudioTimer = setInterval(async () => {
//       if (!playingLock) {
//         await playNextAudio();
//         clearInterval(checkNextAudioTimer);  // 清除定时器
//       }
//     }, 300); // 每秒检查一次
//   } catch (error) {
//     console.error(`播放音频序号 ${nextAudio.orderId} 时出错:`, error);
//     // 如果某个音频播放失败，跳过这个音频，继续播放下一个
//     audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);  // 移除报错的音频
//     playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录
//     playingLock = false;  // 解除锁定
//     // 继续播放下一个音频
//     await playNextAudio();
//   }
// };

// 获取下一个应该播放的音频（保证顺序）
// const getNextAudioToPlay = () => {
//   // 检查音频队列中是否有下一个应该播放的音频
//   console.log("检查下一个播放的音频...");
//   for (let i = 0; i < audioQueue.length; i++) {
//     const audio = audioQueue[i];
//     // 找到最小的序号，即请求的顺序号
//     if (audio.orderId === playingQueue.length) {
//       console.log(`找到了下一个应该播放的音频，序号：${audio.orderId}`);
//       return audio;
//     }
//   }
//   console.log("没有找到下一个应该播放的音频，返回 null");
//   return null;  // 如果没有找到匹配的音频，返回 null
// };

// 播放音频的方法
const playAudio = (audioData) => {
  return new Promise((resolve, reject) => {
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
    const blob = new Blob([audioData], { type: "audio/wav" });
    const url = URL.createObjectURL(blob);
    const audioBufferSourceNode = audioContext.createBufferSource();

    fetch(url)
        .then((response) => {
          if (!response.ok) {
            console.error("音频文件请求失败: ", response.statusText);
            reject(new Error("音频文件请求失败"));
            return;
          }
          return response.arrayBuffer();
        })
        .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer))
        .then((audioBuffer) => {
          audioBufferSourceNode.buffer = audioBuffer;
          audioBufferSourceNode.connect(audioContext.destination);

          audioBufferSourceNode.start(0);

          // 当音频播放完毕时，调用 resolve
          audioBufferSourceNode.onended = () => {
            URL.revokeObjectURL(url);
            resolve();  // 播放完成后，继续播放下一个
          };

          audioBufferSourceNode.onerror = (error) => {
            console.error("音频播放错误:", error);
            URL.revokeObjectURL(url);
            reject(error);  // 播放失败时，返回错误
          };
        })
        .catch((error) => {
          console.error("音频加载或解码时出错:", error);
          reject(error);  // 如果解码或播放出错，reject
        });
  });
};
// const playTTS1 = async (ttsMessage) => {
//   try {
//     const res = await axios.post(
//       `/openapi-stg/ai/voice/tts/v2`,
//       { sessionId: "N7FB_G0WlrOLjc", text: ttsMessage },
//       {
//         responseType: "arraybuffer",
//         headers: {
//           "X-Ai-TTS-Appid": "2b1317fb5b284b308dc90a6fdeae6c4e",
//         },
//       }
//     );
//     console.log(res.data);

//     queue1.add(async () => {
//       // 播放获取到的音频
//       await playAudio(res.data);
//     });
//   } catch (error) {
//     console.error("Error calling TTS API:", error);
//   }
// };

// const playAudio1 = (audioData, options = {}) => {
//   return new Promise((resolve, reject) => {
//     const blob = new Blob([audioData], { type: "audio/wav" });
//     const url = URL.createObjectURL(blob);
//     const audio = new Audio(url);

//     audio.setAttribute("id", "audio");
//     audio.setAttribute("autoplay", "autoplay");

//     if (options.volume) {
//       audio.volume = options.volume; // 设置音量
//     }

//     audio.onended = () => {
//       URL.revokeObjectURL(url);
//       resolve();
//     };

//     audio.onerror = (error) => {
//       URL.revokeObjectURL(url);
//       reject(error);
//     };

//     audio
//       .play()
//       .then(() => console.log("Audio playing"))
//       .catch(reject);
//   });
// };

const chatGpt = async (userMessage) => {
  const downloadUrl = "/openapi-prd/ai/intelligent-tutoring/task/dialogue";
  i = 0;
  queue2.add(() => delay(3000));
  try {
    const response = await axios.post(
      downloadUrl,
      {
        conversationId: conversationId.value,
        content: userMessage,
      },
      {
        headers: {
          "Content-Type": "application/json",
        },
        onDownloadProgress: ({ event }) => {
          const xhr = event.target;
          let { responseText } = xhr;
          console.log("responseText", responseText);
          if (responseText.includes("code") && responseText.includes("400")) {
            // console.log("responseTextcode", responseText);
            // 更新聊天列表
            const text = "我没有听清，麻烦在重复一下。";
            updateChatList(text, false);
            queue.add(async () => {
              await splitMessage(text);
            });
          } else {
            // 用于语音播报
            queue.add(async () => {
              await splitMessage(responseText);
            });
            
            queue2.add(async () => await updateChatList(responseText));
            
            //updateChatList(responseText);
          }
        },
      }
    );
    setTimeout(() => {
         handleTaskStatus()
     },3000)
    //queue2.add(async () => await updateChatList("", false));
  } catch (error) {
    //updateChatList("", false);
    console.error("出错:", error);
  }
};

const chatGpt2 = (userMessage) => {
  const params = {
    conversationId: "2c64eb8b69be432ca0bb9ae55bc78def",
    content: userMessage,
  };
  const ctrlAbout = new AbortController();
  fetchEventSource(
    "https://fls-ai.pingan.com.cn/openapi/ai/intelligent-tutoring/task/dialogue",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json", // 文本返回格式
      },
      body: JSON.stringify(params),
      signal: ctrlAbout.signal,
      openWhenHidden: true, // 在浏览器标签页隐藏时保持与服务器的EventSource连接
      onmessage(res) {
        // 操作流式数据
        console.log(JSON.parse(res.data), "==========");
      },
      onclose(res) {
        // 关闭流
      },
      onerror(error) {
        // 返回流报错
      },
    }
  );
};

const chatGpt1 = async (userMessage) => {
  const downloadUrl =
    "https://fls-ai.pingan.com.cn/openapi/ai/llm/forward/api/ai/nlp/dialogue";

  try {
    const response = await axios.post(
      downloadUrl,
      {
        conversationId: "1976cfe3a5174f9ba768677f789cad7e",
        content: `${userMessage}，请输出纯文本的回答，不要使用markdown输出`,
        messageId: Date.now(),
        applicationId: "",
      },
      {
        headers: {
          "Team-Id": "123456",
          Authorization: "9b2f86c99b5847739045e6b85f355301",
          "Content-Type": "application/json",
        },
        onDownloadProgress: ({ event }) => {
          const xhr = event.target;
          const { responseText } = xhr;
          console.log(responseText);
          // 更新聊天列表
          updateChatList(responseText);
          // 用于语音播报
          queue.add(async () => {
            await splitMessage(responseText);
          });
        },
      }
    );
    updateChatList("", false);
  } catch (error) {
    updateChatList("", false);
    console.error("下载文件时出错:", error);
  }
};
const next = () => {
  router.push({
    name: "result",
    query: { conversationId: conversationId.value,scenceType:scenceType.value },
  });
};

const loadChatHistory = () => {
  
  const chatHistory = localStorage.getItem("chatHistory");
  const chatStatus = localStorage.getItem("status");
  if (chatHistory) {
    const history = JSON.parse(chatHistory);
    history.forEach((item) => {
      chatList.value.push(item);
    });
  }
  if(chatStatus){
    taskStatus.value = JSON.parse(chatStatus)
  }
};

// 查询任务结束状态

const handleTaskStatus = async () => {
  const res =  await fetchTaskStatus(conversationId.value)
  if(res.code == 200){
    taskStatus.value = res.body
    localStorage.setItem("status", res.body);
  }
}

// 在组件挂载时调用
onMounted(() => {
  loadChatHistory();
  setTimeout(() => {
    loading.value = false;
  }, 2000);
});

</script>

<template>
  <div class="main">
    <nav-bar-page title="考试" />
    <div class="rate-circle">
      <van-circle
        :stroke-width="80"
        size="70px"
        v-model:current-rate="currentRate"
        :rate="rate"
        :text="text"
      />
    </div>
     <div class="tooltip">
      <p>拜访客户现场情况：</p>
      <p>1. 门口有招聘广告，进入厂区需登记</p>
      <p>2. 会议室有产品展示柜，参观了车间和厂区，车间管理规范</p>
    </div>
    <BG />
    <div class="loading" v-show="loading">
      <van-loading color="#0094ff" size="26px" vertical>加载中...</van-loading>
    </div>
    
    <ChatList :chatList="chatList" />
    <BottomArea
      @startRecord="handleStartRecord"
      @stopRecord="handleStopRecord"
      v-show="rate < 100 || taskStatus"
    />
    <div v-show="rate >= 100 || taskStatus" class="next-btn">
      <van-button style="width: 100%" @click="next" type="primary"
        >已完成对话，下一步</van-button
      >
    </div>
  </div>
</template>
<style>
* {
  -webkit-touch-callout: none; /*系统默认菜单被禁用*/
  -webkit-user-select: none; /*webkit浏览器*/
  -khtml-user-select: none; /*早期浏览器*/
  -moz-user-select: none; /*火狐*/
  -ms-user-select: none; /*IE10*/
  user-select: none;
}
</style>

<style scoped>
.main {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.rate-circle {
  position: fixed;
  right: 20px;
  top: 70px;
  z-index: 9999;
}
.tooltip {
  width: 85%;
  position: fixed;
  top: 150px;
  left: 50%;
  /* 左边到视口宽度的一半 */
  transform: translateX(-50%);
  /* 再左移自身宽度的一半，实现居中 */
  z-index: 9999;
  font-size: 12px;
  padding: 8px 12px;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
 padding-left: 20px;
 box-sizing: border-box;
 border-radius: 10px;
}
.next-btn {
  position: fixed;
  bottom: calc(20px + env(safe-area-inset-bottom));
  width: 100%;
  box-sizing: border-box;
  padding: 0 20px;
}
.loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}
</style>
