<!-- Chat.vue -->
<template>
  <div class="chat-container">
    <div v-if="!messages.length && !msgLoading" class="message-list">
      <pageMask />
    </div>
    <!-- 消息列表 -->
    <div class="message-list" v-else >
      <el-scrollbar ref="scrollbar" @scroll="handleScroll" v-loading="msgLoading">
        <!-- 加载更多指示器 -->
        <div v-if="isLoadingMore" class="loading-more-indicator">
          <div class="loading-spinner"></div>
          <span>加载更多消息...</span>
        </div>
        <div class="messages" ref="messagesContainer" >
          <div v-for="(message, index) in messages" :key="index"
            :class="['message-item', message.role === 'user'  ? 'self' : 'other']">
            <el-avatar :size="32" :src="message.role === 'user' ? userAvatar : avatar" />
            <div class="message-content">
              <div class="content" v-if="message.role ==='system'"
                :class="{ 'loading-content': message.content === '' }">
                <formTable v-if="message.type === 'form'" :content="message.rawContent" />
                <span v-else v-html="message.content"></span>
                <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
                  <span class="dot"></span>
                  <span class="dot"></span>
                  <span class="dot"></span>
                </span>
              </div>
              <document v-else-if="message.type === 'document' && message.role === 'user'" :content="message.content"
                :rawContent="message.rawContent" />
              <div v-else class="content">
                <span v-if="message.type === ''">{{ message.content }}</span>
                <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
                  <span class="dot"></span>
                  <span class="dot"></span>
                  <span class="dot"></span>
                </span>
              </div>
              <div class="timestamp ">{{ moment(message.sortKey).format('MM-DD HH:mm') }}
                <!-- <span v-if="message.add" style="cursor: pointer;" @click="handleInput">填充</span> -->
              </div>
            </div>
          </div>
        </div>
      </el-scrollbar>
      <ScrollToBottom :target="scrollbar" ref="scrollToBottomRef" />
    </div>

    <Tools @read-click="readClick" @upload-file="(file) => createFileObj(file)" @handle-capture="handleCapture" @his-records="hisRecords"
      @add-new-dialogue="addNewDialogue" @handle-current-change="handleCurrentChange"
      @handel-intelligent-filling-click="handelIntelligentFillingClick" />

    <div>
      <!-- 输入区域 -->
      <div class="input-area">
        <div v-show="isShowPage" style="border-bottom: 1px solid #F0F0F0;">
          <div class="card_list">
            <div v-for="(v, i) in pageInfoList" :key="i"
              :class="`card-content ${pageInfoList.length > 1 ? 'card_width' : ''}`">
              <div class="loading-more-indicator" v-if="v.loading">
                <div class="loading-spinner"></div>
              </div>
              <img v-else :src="v?.favIconUrl" style="width: 24px;display: block" />

              <div class="title-wrapper">
                <span class="els title-scroller">{{ v?.title }}</span>
                <span class="els url-scroller">{{ v.loading ? v?.state : v?.url }}</span>
              </div>
              <el-icon class="closeIcon" size="16px" color="#909399" @click="deletePageInfo(i)">
                <CircleClose />
              </el-icon>
            </div>
          </div>

          <div class="card-btn">
            <el-tooltip  content="总结当前页面" placement="top">
              <el-button :disabled="disabledBtn" v-if="type !== FunctionList.Intelligent_Form_filling"  round @click="handleSummary">总结</el-button>
            </el-tooltip>
             <el-tooltip   content="抽取表单信息" placement="top">
              <el-button :disabled="disabledBtn" v-if="type === FunctionList.Intelligent_Form_filling && pageInfoList.length" round @click="handleSummaryFile">抽取</el-button>
            </el-tooltip>
          </div>
        </div>

        <el-input ref="textareaRef" v-model="inputMessage" type="textarea" :rows="3" placeholder="输入消息..."
          @keyup.enter="() => handleAsk()" />
        <div class="chat_area_op">
          <el-button
            :style="`background-color:${inputMessage.trim() ? '#4d6bfe' : '#d6dee8'};border-color:${inputMessage.trim() ? '#4d6bfe' : '#d6dee8'}`"
            v-if="inputMessage.trim() || !sendLoading" type="primary" circle @click="() => handleAsk()"
            :disabled="!inputMessage.trim() || sendLoading">
            <svg-icon icon-class="send" color="#000000" />
          </el-button>
          <el-button style="background-color:#ffffff;border:2px solid rgb(134 143 153);" v-else circle
            @click="handleStopAsk">
            <svg-icon icon-class="stop" color="red" />
          </el-button>
        </div>
      </div>

    </div>


    <!--  历史记录  -->
    <historyComponent :msgUuid="msgUuid" ref="historyComponentRef" @currentData="(e) => handleCurrentData(e)" />
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, inject, useTemplateRef, reactive } from 'vue'
import { ElScrollbar, ElAvatar, ElInput, ElButton } from 'element-plus'
import moment from 'moment'
import fileLogo from '@/assets/svg/file.svg'
import {
  buildExcelUnderstandingPrompt,
  getSummaryPrompt,
  getFileContent,
  buildObjPrompt,
  modelFileUpload,
  controllerList,
  formatMessage
} from '@/entrypoints/sidepanel/utils/ai-service.js'
import { storeToRefs } from 'pinia'
import { ElMessage } from 'element-plus'
import { useMsg } from '@/entrypoints/sidepanel/hook/useMsg.ts'
import Tools from '@/entrypoints/sidepanel/component/tools.vue'
import historyComponent from '@/entrypoints/sidepanel/component/historyComponent.vue'
import document from '@/entrypoints/sidepanel/component/document.vue'
import pageMask from '@/entrypoints/sidepanel/component/pageMask.vue'
import ScrollToBottom from '@/entrypoints/sidepanel/component/ScrollToBottom.vue'
import formTable from '@/entrypoints/sidepanel/component/formTable.vue'
import userAvatar from '@/assets/images/user.png'
import avatar from '@/public/icon/32.png'
import { mockData, startMsg, mockData2, options, FunctionList } from '@/entrypoints/sidepanel/mock'
import { useAutoResizeTextarea } from '@/entrypoints/sidepanel/hook/useAutoResizeTextarea.ts'
import { getPageInfo, getXlsxValue, handleInput } from './utils/index.js'
import { useMsgStore } from '@/store/modules/msg.ts'
import { useUserStore } from '@/store/modules/user'
import { putChat, uploadFile } from "@/api/index.js";
import {askQues,getFormKey} from '@/api/modal.js'
import { debounce } from 'lodash'
import request from '@/utils/request'
import  EventSourcePolyfill  from 'eventsource-polyfill';
const userStore = useUserStore()
import { getChatDetail } from '@/api/index.js'
// 在其他状态变量附近添加
const isLoadingMore = ref(false)
import { v4 as uuidv4 } from 'uuid';
import content from '../content.js'
// 滚动条引用
const scrollbar = ref(null)
const scrollToBottomRef = ref(null)
const xlsxData = ref({})
const isShowPage = ref(false)
const tareRef = useTemplateRef('textareaRef')
const drawerRef = useTemplateRef('historyComponentRef')
// 获取父组件提供的 Hook 实例
const msgStore = useMsgStore()
const { pageInfoList, messages, msgUuid, AIModel,page,hasNext,msgLoading } = storeToRefs(useMsgStore())
const formInfo = ref('')
const {
  taklToHtml,
  sendLoading,
  type,
  streamRes,
  getFormKeyAndValue,
  requestFlowFn,
  fetchRes
} = useMsg(scrollbar)
const inputMessage = ref('')
const pageInfo = ref('')
const summaryHtml = ref(false)
function handleStopAsk() {
  if (type.value === FunctionList.Intelligent_Form_filling) {
    inputMessage.value = ''
    pageInfoList.value = []
    isShowPage.value = false
    taklToHtml.value = false
    type.value = FunctionList.File_Operation
  }
  controllerList.value[0].abort()
  controllerList.value = []
  sendLoading.value = false
}

function handleScroll(a) {
  const { wrapRef } = scrollbar.value
  const { scrollHeight, clientHeight } = wrapRef
  scrollToBottomRef.value.showButton = scrollHeight - a.scrollTop - clientHeight >= 350
  
  // 检测是否滚动到顶部
  if (a.scrollTop <= 10 && hasNext.value) {
    handleScrollToTop()
  }
}
const messagesContainer = ref(null)
let innerText = ''
// 处理滚动到顶部的事件
const handleScrollToTop = debounce(async function () {
  console.log('滚动到顶部，可以加载更多历史消息')
  if (!sendLoading.value && !isLoadingMore.value) {
    isLoadingMore.value = true
    try {
      // 记录当前第一条消息的位置
      const firstMessage = messagesContainer.value?.firstElementChild.querySelector('.timestamp')
      innerText = firstMessage.innerText
      const oldHeight = firstMessage?.offsetTop || 0
      await msgStore.changePage()
      setTimeout(() => {
        if (firstMessage) {
          console.log([...messagesContainer.value.querySelectorAll('.timestamp')].find(_ => _.innerText === innerText).offsetTop, innerText, 778);
          const newHeight = [...messagesContainer.value.querySelectorAll('.timestamp')].find(_ => _.innerText === innerText).offsetTop
          const scrollOffset = newHeight - oldHeight
          scrollbar.value?.setScrollTop(scrollOffset)
        }
      }, 400);
      // 恢复滚动位置
     
    } finally {
      isLoadingMore.value = false
    }
  }
}, 500, { leading: false, trailing: true })
/**
 * @param {string} msg
 * @param {string} raw
 * @param {string} type 发送的类型 document 、text
 * **/
async function addMessage(msg, raw, type) {
  const newMessage = reactive({
    id:+new Date(),
    type: type || '',
    rawContent: raw ?? msg,
    senderId: userStore.userInfo.id,
    receiverId:-1, //大模型
    content: msg,
    sortKey: moment().valueOf(),
    role: 'user',
    conversationId:msgUuid.value,
    addToHistory: `${!taklToHtml.value}`,
    redisKey: undefined,
    fileId:undefined
  })
  if (type === 'document') {
    newMessage.content = msg
    newMessage.rawContent = raw
  }
  if (!msg) return
  messages.value.push(newMessage)
  nextTick(() => {
    if (scrollbar.value && scrollbar.value.wrapRef) {
      scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
    }
  })
  return newMessage
}

const handleSummary = async () => {
  if(sendLoading.value) return
  handleAsk(`请帮我总结当前${summaryHtml.value ? '页面' : '文件'}`)
  summaryHtml.value = false
}
const handleSummaryFile = async () => {
  if (sendLoading.value) return
 try {
   sendLoading.value = true
   const  userMsg = await addMessage(JSON.stringify([...pageInfoList.value, { type: 'text', value: '抽取表单' }]), '抽取表单', 'document')
    userMsg.fileId = pageInfoList.value[0].fileId
    userMsg.redisKey = pageInfoList.value[0].redisKey
    await putChat(userMsg)
    const msg = reactive({
    type: '',
    rawContent: '',
    senderId: -1,
    receiverId: userStore.userInfo.id, //大模型
    content: '',
    sortKey: moment().valueOf(),
    role: 'system',
    conversationId: msgUuid.value,
    })
  messages.value.push(msg)
     isShowPage.value = false
  pageInfoList.value = []
    const resForm = await askQues({
    conversationId: msgUuid.value,
    modelName: '通义千问-Max',
    question: buildObjPrompt(xlsxData.value,formInfo.value),
    id: '699637194561691650',
    // redisKey:msg.redisKey
    })
  return console.log(resForm);
  
  const formResult = resForm.data[0].content
    let form = null
    if (formResult.includes('json')) form = JSON.parse(formResult.split('json')[1].split('```')[0])
          else form = JSON.parse(formResult)
  msg.type = 'form'
  // 保存原始内容
  msg.rawContent = formResult
  putChat({
    ...msg
  })
  sendLoading.value = false
  handleInput(xlsxData.value, form)
    nextTick(() => {
    if (scrollbar.value && scrollbar.value.wrapRef) {
      scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
    }
  })
 } catch (error) {
  
 } finally {
   sendLoading.value = false
  type.value = FunctionList.File_Operation
 }
}
async function handelIntelligentFillingClick() {
  // isShowPage.value = true
  // taklToHtml.value = true
  // const tempPageInfo = await getPageInfo()
  // pageInfo.value = tempPageInfo
  // pageInfoList.value = [tempPageInfo]
  inputMessage.value = '/智能填表 '
  type.value = FunctionList.Intelligent_Form_filling
}

function handleCurrentChange(e) {
  options.forEach((item) => {
    item.options.forEach((item2) => {
      if (item2.value === e) {
        msgStore.updateAIModel(item2)
      }
    })
  })
  if (AIModel.value.file === true) {
    isShowPage.value = false
    taklToHtml.value = false
    pageInfoList.value = []
  }
}

async function handleCurrentData(e) {
  drawerRef.value.drawer = false
  if (!e) {
    addNewDialogue()
    return
  }
  messages.value = []
  page.value = 1
  msgUuid.value = e
  chrome.storage.local.set({ msgUuid: msgUuid.value })
  await msgStore.initMsg()
  nextTick(() => {
  if (scrollbar.value && scrollbar.value.wrapRef) {
    scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
  }
})
}

async function readClick() {
  if (type.value === FunctionList.Intelligent_Form_filling) {
    pageInfoList.value = []
    type.value = FunctionList.File_Operation
  }
  summaryHtml.value = true
  isShowPage.value = true
  taklToHtml.value = true
  if (pageInfoList.value.length >= Number(import.meta.env.VITE_MAX_FILE_NUMBER)) {
    ElMessage.warning(`最多添加${import.meta.env.VITE_MAX_FILE_NUMBER}个文件`)
    return
  }
  const tempPageInfo = await getPageInfo()
  const blob = new Blob([tempPageInfo.content.mainContent], { type: 'text/plain' })
  const file = new File([blob], tempPageInfo.title + '.txt', { type: 'text/plain' })
  await createFileObj(file)
  // await handleUpload(file,tempPageInfo.title + '.txt')
}

function deletePageInfo(i) {
  pageInfoList.value.splice(i, 1)
  if (pageInfoList.value.length === 0) {
    isShowPage.value = false
    taklToHtml.value = false
    if (type.value === FunctionList.Intelligent_Form_filling) inputMessage.value = ''
    type.value = FunctionList.File_Operation
  }
}

function addNewDialogue() {
  if (messages.value.length === 0) {
    ElMessage.warning('已经是新对话')
    return
  }
  isShowPage.value = false
  taklToHtml.value = false
  messages.value = []
  page.value = 1
  pageInfoList.value = []
  msgUuid.value = uuidv4()
  hasNext.value = false
  chrome.storage.local.set({ msgUuid: msgUuid.value })
}
const disabledBtn = computed(() => {
 return  !!(pageInfoList.value.find(_ => _.loading ))
})
async function handleAsk(value) {
  const str = value ?? inputMessage.value.trim()
  inputMessage.value = ''
  if (type.value === FunctionList.Intelligent_Form_filling) {
     await addMessage(str)
     const res = await fetchRes(str)
    if (res.status === 'ok') {
      formInfo.value = res.data
    } else {
      type.value = FunctionList.File_Operation
    }
    return 
  }
  if (sendLoading.value) return
  let msg = null
  if (pageInfoList.value.length) {
    msg = await addMessage(JSON.stringify([...pageInfoList.value, { type: 'text', value: str }]), str, 'document')
    msg.fileId = pageInfoList.value[0].fileId
    msg.redisKey = pageInfoList.value[0].redisKey
  } else msg = await addMessage(str)
  await putChat(msg)
  sendLoading.value = true
  const obj = reactive({
    type: type || '',
    rawContent: '',
    senderId: -1,
    receiverId: userStore.userInfo.id, //大模型
    content: '',
    sortKey: moment().valueOf(),
    role: 'system',
    conversationId: msgUuid.value,
  })
  messages.value.push(obj)
  nextTick(() => {
    if (scrollbar.value && scrollbar.value.wrapRef) {
      scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
    }
  })
  // request.post('/ai/model/question',{
  //   conversationId: msgUuid.value,
  //   modelName: '通义千问-Max',
  //   question: msg.rawContent,
  //   id: '699637194561691650',
  //   // redisKey:msg.redisKey
  //   }, {
  //   onDownloadProgress: progressEvent => {
  //     console.log('progressEvent', progressEvent)
  //     let { responseText } = progressEvent.event.target
  //     const newData = responseText.slice(buffer.length)
  //     buffer += newData
  //     // const events = buffer.split('\n\n')
  //     const events = buffer.split('\n\n').map(item => {
  //       const data = item.replace(/^data: /, '').trim()
  //       // return data
  //       try {
  //         return JSON.parse(data)
  //       } catch (error) {
  //         return ''
  //       }
  //     })
  //     debugger
  //     buffer = events.pop() // 剩余部分保留到下一次
  //     // events.forEach(event => {
  //     //   if (event.trim()) {
  //     //     const data = event.replace(/^data: /, '').trim();
  //     //     const infoData = JSON.parse(data);
  //     //     console.log('Received event:', infoData.message);
  //     //   }
  //     // });
  //     console.log('Received data:', events, 'aaa', buffer)
  //   }
  // })
  // 使用 WebSocket 替代 EventSource
  try {
    // 创建 WebSocket 连接
     await askQues({
    conversationId: msgUuid.value,
    modelName: '通义千问-Max',
    question: msg.rawContent,
    id: '699637194561691650',
    // redisKey:msg.redisKey
    })
    const wsUrl = `${import.meta.env.VITE_API_WS_URL}/webSocket/${msgUuid.value}`;
    console.log(wsUrl,12312);
    
    const socket = new WebSocket(wsUrl);
    // 连接建立时发送消息
    socket.onopen = () => {
      console.log('WebSocket 连接已建立');
      // 发送请求数据
      socket.send(JSON.stringify({
     session:msgUuid.value
      }));
    };
    
    // 接收消息
    socket.onmessage = (event) => {
      try {
        console.log('收到数据:', event);

        // const data = JSON.parse(event.data);
        // console.log('收到数据:', data);
        return
        // 追加内容
        if (data.content) {
          obj.content += data.content;
          obj.rawContent += data.content;
          
          // 滚动到底部
          nextTick(() => {
            if (scrollbar.value && scrollbar.value.wrapRef) {
              scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight);
            }
          });
        }
        
        // 如果是最后一条消息，关闭连接
        if (data.done) {
          socket.close();
          sendLoading.value = false;
          
          // 保存到数据库
          putChat({
            ...obj,
            content: obj.content
          });
          
          isShowPage.value = false;
          pageInfoList.value = [];
        }
      } catch (error) {
        console.error('解析消息出错:', error);
      }
    };
    
    // 处理错误
    socket.onerror = (error) => {
      console.error('WebSocket 错误:', error);
      socket.close();
      sendLoading.value = false;
      
      // 如果没有收到任何内容，显示错误消息
      if (!obj.content) {
        obj.content = '连接出错，请重试';
        // 保存到数据库
        putChat({
          ...obj,
          content: obj.content
        });
      }
    };
    
    // 连接关闭
    socket.onclose = () => {
      console.log('WebSocket 连接已关闭');
      sendLoading.value = false;
    };
    
    // 添加到控制器列表，以便可以在需要时中断连接
    controllerList.value.push({
      abort: () => {
        socket.close();
      }
    });
  } catch (error) {
    console.error('创建 WebSocket 失败:', error);
    sendLoading.value = false;
    
    // 显示错误消息
    obj.content = '连接失败，请重试';
    
    // 保存到数据库
    putChat({
      ...obj,
      content: obj.content
    });
  }
  
  // 移除原有的 EventSource 代码
  // const params = new URLSearchParams({...});
  // const eventSource = new EventSource(...);
  // ...
}
function handleCapture() {
  ElMessage({
    message: '开发中...',
    grouping: true,
    showClose: true
  })
}
function hisRecords() {
  drawerRef.value.drawer = true
}
const createFileObj = async (file) => {
  handleUpload(file)
}
const handleUpload = async (file) => {
  if (type.value === FunctionList.Intelligent_Form_filling) {
    pageInfoList.value = []
  }
  isShowPage.value = true
  const obj = reactive({
    title: file.name,
    state: '上传中...',
    favIconUrl: fileLogo,
    loading: true,
    url:'',
    fileId: '',
    redisKey:'',
    content: {
      mainContent: ''
    }
  })
  pageInfoList.value = [obj]
  try {
    let formData = new FormData()
    formData.append('avatarFile', file)
    const res = await uploadFile(formData)
  if (type.value === FunctionList.Intelligent_Form_filling) {
    obj.state = '解析中...'
    obj.redisKey = res.data.redisKey
    obj.id = res.data.file.id
    obj.url = res.data.file.url
    const fileExtension = file.name.split('.').pop().toLowerCase()
    if (fileExtension === 'xlsx') {
          const readData = await getXlsxValue(file)
      readData[0].forEach((header, i) => {
        // if (!xlsxData.value[header]) xlsxData.value[header] = []
        xlsxData.value[header] = readData[1][i]
      })
    } else {
         const result = await getFormKey({
      body: formInfo.value,
      input_data:res.data.data
    })
    xlsxData.value = JSON.parse(result.data)
      }
    }
 
   nextTick(() => {
  if (scrollbar.value && scrollbar.value.wrapRef) {
    scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
  }
})
  if (type.value === FunctionList.File_Operation) {
    obj.loading = false
    obj.url = res.data.url
    obj.redisKey = res.data.redisKey
    obj.fileId = res.data.file.id
    obj.url = res.data.file.url
    }
  obj.loading = false
  } catch (error) {
    console.log(error);
    
    ElMessage.error('上传出错')
    pageInfoList.value = []
    isShowPage.value = false
  }
}
async function getFileValue(file) {
  let formData = new FormData()
  formData.append('file', file)
  const res = await getFileContent(formData)
  return res.data
}
let a = null
// 组件挂载时滚动到底部
onMounted(async () => {
  msgStore.updateAIModel(options[0].options[0])
  await msgStore.initMsg()
  useAutoResizeTextarea(tareRef, inputMessage)
  chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === 'TO_SIDE_PANEL_PAGE_INFO') {
      pageInfo.value = message.data
      // 转发到 content.js
      chrome.tabs.sendMessage(sender.tab.id, {
        type: 'TO_CONTENT_SCRIPT',
        data: message.data
      })
    }
    if (message.type === 'TO_SIDE_PANEL_PAGE_CHANGE') {
      pageInfo.value = message.data
    }
  })
 nextTick(() => {
  if (scrollbar.value && scrollbar.value.wrapRef) {
    scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
  }
})
})
</script>

<style lang="scss" scoped>
@use '@/entrypoints/sidepanel/css/chat.scss';
@use '@/entrypoints/sidepanel/css/markdown.scss';

.loading-more-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 0;
  color: #909399;
  font-size: 14px;
  
  .loading-spinner {
    width: 20px;
    height: 20px;
    margin-right: 8px;
    border: 2px solid #e6e6e6;
    border-top-color: #4d6bfe;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
</style>
