<template>
  <div :class="['FAQ-container',!historyShow ? 'FAQ-width' : '']">
    <div :class="['container']">
      <div class="title">
        <span class="front">海知无涯，智慧伴航，千帆智瞰，</span>
        <span class="behind">引领你探索未知的海域</span>
      </div>
      <!-- 对话框内容 -->
      <DialogRealCom @openVideo="openVideo" @openUav="openUav" v-if="dialog && type === 'real'" :answers="answers"/>
      <DialogHistoryCom @openVideo="openVideo" v-if="dialog && type === 'history'" :answers="answers"/>
      <div class="introduceRecommend" v-if="!dialog">
        <div class="introduce">
          <img src="@/assets/images/largeModel/icon-robot.png" alt="">
          <div class="content">
            <div v-for="(i,index) in describe" :key="index">{{i}}</div>
          </div>
        </div>
        <div class="recommend">
          <div class="header">
            <div class="title">
              <img src="@/assets/images/largeModel/icon-recommend.png" alt="">
              推荐
            </div>
          </div>
          <div class="content">
              <div class="row" v-for="(item, index) in recommends" :key="index" @click="command(item)">
                <div class="desc">{{index+1}}. {{ item }}</div>
              </div>
            </div>
        </div>
      </div>
    </div>
    <div class="input-container">
        <!-- 图片预览区域 - 放在输入框上方 -->
        <div v-if="previewImages.length > 0" class="image-preview-inline">
          <div class="image-item" v-for="(image, index) in previewImages" :key="index">
            <img :src="image.url" alt="预览图片" />
            <el-icon class="image-actions" @click="removeImage(index)"><Close /></el-icon>
          </div>
        </div>
        <el-input
          v-model="message"
          placeholder="点这里，尽管问"
          :autosize="{ minRows: 2, maxRows: 10 }"
          type="textarea"
          @keyup.enter="send"
        />
        <div class="input-actions">
          <!-- <div class="button" @click="startSpeechRecognition" title="语音输入">
            <img src="@/assets/images/largeModel/icon-voice.png" alt="">
          </div> -->
          <!-- <div class="button" title="上传图片">
            <img src="@/assets/images/largeModel/icon-upload.png" alt="" @click="triggerFileInput">
            <input
              ref="fileInput"
              type="file"
              accept="image/*"
              multiple
              @change="handleFileUpload"
              style="display: none;"
            />
          </div> -->
          <div class="button" @click="handleClick" :style="loading ? {background: 'linear-gradient(90deg, #1d91fe85 0%, #536ce8ab 100%)'} : {}">
            <el-icon class="loading" v-if="loading"><Loading /></el-icon>
            <img v-else src="@/assets/images/largeModel/icon-send.png" alt="">
          </div>
        </div>
      </div>
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
import DialogRealCom from './realDialog.vue'
import DialogHistoryCom from './historyDialog.vue'
import { dayjs } from 'element-plus'
import { Close, Loading } from '@element-plus/icons-vue'
import { getAnswers, restart } from '@/api/model.js'
import axios from 'axios'

const emit = defineEmits([ 'initList', 'openVideo', 'openUav' ])
const props = defineProps({
  historyShow: {
    type: Boolean,
    default: true
  }
})
// 添加流式输出相关变量
const answersBuffer = ref('')
const isStreaming = ref(false)
// 添加文件上传相关的响应式变量
const fileInput = ref(null)
const previewImages = ref([])
const selectedFiles = ref([])

const getPeriod = computed(() => {
  const hour = dayjs().hour()
  if (hour >= 0 && hour < 6) {
    return '凌晨'
  }
  if (hour >= 6 && hour < 12) {
    return '上午'
  }
  if (hour >= 12 && hour < 18) {
    return '下午'
  }
  return '晚上'
})
const message = ref('')
const describe = ref([])
const recommends = ref()
const loading = ref(false)
// 对话框
const dialog = ref(false)
const type = ref('real')
const answers = reactive({})
// 语音录入
let speechRecognition = null
const isListening = ref(false)
let resizeObserver = null

const openVideo = (data) => {
  emit('openVideo', data)
}
const openUav = (data) => {
  emit('openUav', data)
}
// 触发文件选择
const triggerFileInput = () => {
  fileInput.value.click()
}

// 处理文件上传
const handleFileUpload = (event) => {
  const files = event.target.files
  if (files.length === 0) {
    return
  }

  // 验证文件类型
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    if (file.type.startsWith('image/')) {
      // 创建预览
      const reader = new FileReader()
      reader.onload = (e) => {
        previewImages.value.push({
          url: e.target.result,
          name: file.name,
          size: file.size
        })
      }
      reader.readAsDataURL(file)

      // 存储原始文件
      selectedFiles.value.push(file)
    } else {
      alert(`请选择有效的图片文件: ${file.name}`)
    }
  }
}
// 移除单个图片
const removeImage = (index) => {
  previewImages.value.splice(index, 1)
  selectedFiles.value.splice(index, 1)
  if (fileInput.value) {
    fileInput.value.value = ''
  }
}
// 清除所有图片
const clearAllImages = () => {
  previewImages.value = []
  selectedFiles.value = []
  if (fileInput.value) {
    fileInput.value.value = ''
  }
}
// 点击推荐
const command = (item) => {
  message.value = item
  nextTick(() => {
    send()
  })
}
// 终止回答
const stop = () => {
  axios.post(restart, {}, {
    headers: {
      'Content-Type': 'application/json'
    }
  }).then(() => {
  }).finally(() => {
    loading.value = false
  })
}
const send = () => {
  if(!loading.value && (message.value !== '' || previewImages.value.length > 0)) {
    loading.value = true
    answersBuffer.value = ''
    isStreaming.value = true
    // 先清空
    Object.keys(answers).forEach(key => {
      answers[key] = ''
    })
    dialog.value = true
    type.value = 'real'
    // 请求问答
    let params = { query: message.value }
    answers.query = message.value
    answers.previewImages = previewImages.value
    if(previewImages.value.length > 0) {
      params = { query: '查看这艘船的告警信息' }
    }
    fetch(getAnswers, {
        method: 'POST',
        body: JSON.stringify(params),
        headers: {
            'Content-Type': 'application/json' // 根据实际情况设置请求头
        },
        responseType: 'stream'
    }).then(async(res) => {
        // 判断响应是否正常
        if (!res.ok) {
            throw new Error(`HTTP error! status: ${res.status}`)
        }
        const reader = res.body.getReader()
        const decoder = new TextDecoder()
        let result = true
        try {
            while (result) {
                const { done, value } = await reader.read()

                if (done) {
                    result = false
                    break
                }
                // 解码并累加到缓冲区
                decoder.decode(value).split('\n')
                .forEach((val) => {
                    if (!val) {
                    return
                    }
                    try {
                        // 后端返回的流式数据一般都是以data:开头的字符，排除掉data:后就是需要的数据
                        // 具体返回结构可以跟后端约定
                        let txt = val?.replace('data:', '') || ''
                        let data = JSON.parse(txt)
                        if(data?.content) {
                            answersBuffer.value += data.content
                        }else if(data?.mp4_url || data?.image_url || data?.rtsp_url || data?.rtsp_data) {
                          let additionalContent = ''
                          if(data.image_url && Array.isArray(data.image_url)) {
                              additionalContent += '\n' + data.image_url.join(' ') + '\n'
                          }
                          if(data.mp4_url && Array.isArray(data.mp4_url)) {
                              additionalContent += '\n' + data.mp4_url.join(' ') + '\n'
                          }
                          if(data.rtsp_url && Array.isArray(data.rtsp_url)) {
                            console.log('data.rtsp_url', data.rtsp_url)
                            data.rtsp_url.forEach(item => {
                              additionalContent += '\n' + JSON.stringify(item) + '\n'
                            })
                          }
                          if(data.rtsp_data && Array.isArray(data.rtsp_data)) {
                            console.log('data.rtsp_data', data.rtsp_data)
                            data.rtsp_data.forEach(item => {
                              additionalContent += '\n' + JSON.stringify(item) + '\n'
                            })
                          }
                          answersBuffer.value += additionalContent
                        }else{
                            answersBuffer.value += ''
                        }
                        if(data.clear_previous) {
                          answersBuffer.value = ''
                        }
                        answers.answer = answersBuffer.value
                        nextTick(() => {

                        })

                    } catch (err) { }
                })
                // 更新答案内容
            }
        } catch (error) {
            answers.answer = '抱歉，获取回答时出现错误。'
            loading.value = false
        } finally {
            reader.releaseLock() // 显式释放 reader 锁
            loading.value = false
            isStreaming.value = false
        }
    }).catch(error => {
      console.error('请求错误:', error)
      loading.value = false
      isStreaming.value = false
      answers.answer = '抱歉，获取回答时出现错误。'

    }).finally(() => {
      loading.value = false
      message.value = ''
      previewImages.value = []
      selectedFiles.value = []
      clearAllImages()
      emit('initList')
    })
  }
}
const handleClick = () => {
  if(loading.value) {
    stop()
  }else {
    send()
  }
}
// 初始化语音识别
const initSpeechRecognition = () => {
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition
  if (!SpeechRecognition) {
    console.warn('当前浏览器不支持语音识别功能')
    return null
  }
  const recognition = new SpeechRecognition()
  recognition.lang = 'zh-CN' // 设置语言为中文
  recognition.continuous = false // 设置为单次识别
  recognition.interimResults = true // 获取中间结果
  recognition.onstart = () => {
    isListening.value = true
    console.log('语音识别已启动')
  }
  recognition.onresult = (event) => {
    const transcript = Array.from(event.results)
      .map(result => result[0])
      .map(result => result.transcript)
      .join('')
    message.value = transcript
    console.log('识别结果:', transcript)
  }
  recognition.onerror = (event) => {
    console.error('语音识别出错:', event.error)
    isListening.value = false
  }
  recognition.onend = () => {
    isListening.value = false
    console.log('语音识别已结束')
  }
  return recognition
}

// 开始语音识别
const startSpeechRecognition = () => {
  // if (!checkSpeechRecognitionSupport()) {
  //   alert('当前浏览器不支持语音识别功能，请使用Chrome或其他支持Web Speech API的浏览器')
  //   return
  // }
  if (!speechRecognition) {
    speechRecognition = initSpeechRecognition()
  }
  if (isListening.value) {
    // 如果正在监听，则停止
    speechRecognition.stop()
    isListening.value = false
  } else {
    // 开始语音识别
    try {
      speechRecognition.start()
    } catch (error) {
      console.error('启动语音识别失败:', error)
    }
  }
}
const changeDialog = (item) => {
  dialog.value = item.flag
  type.value = 'history'
  if(item.data) {
    Object.keys(JSON.parse(item.data)).forEach(key => {
      answers[key] = JSON.parse(item.data)[key]
    })
  }
  loading.value = false
}
const changeRecommend = (data) => {
  describe.value = data.desc
  recommends.value = data.recommends
}
const observeContainerResize = () => {
  // 查找目标容器元素
  const targetElement = document.querySelector('.large-model-container')
  if (targetElement) {
    // 创建 ResizeObserver 实例
    resizeObserver = new ResizeObserver((entries) => {
      for (let entry of entries) {
        const height = entry.contentRect.height
        if (height < 585) {
          document.querySelector('.introduce').style.display = 'none'
        }else{
          document.querySelector('.introduce').style.display = 'flex'
        }
        if (height < 443) {
          document.querySelector('.recommend').style.display = 'none'
        }else{
          document.querySelector('.recommend').style.display = 'block'
        }
      }
    })
    // 开始观察目标元素
    resizeObserver.observe(targetElement)
  } else {
    console.log('未找到 .large-model-container 元素')
  }
}
onMounted(() => {
  nextTick(() => {
    observeContainerResize()
  })
})
onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect()
  }
})
defineExpose({
  changeDialog,
  changeRecommend
})
</script>

<style lang="scss" scoped>
.FAQ-container {
  position: relative;
  width: calc(100% - 200px);
  box-sizing: border-box;
  font-family: 'SHSCNR';
  &.FAQ-width{
    width: 100%
  }
  .title{
    font-size: 14px;
    font-weight: 500;
    display: inline;
    .front{
      color: #FFFFFF;
    }
    .behind{
      color: #42D9FF;
    }
  }
  .container{
    width: 100%;
    margin: 10% auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
    height: calc(100% - 220px);
    margin: 0 auto;

    background: linear-gradient( 180deg, rgba(2,25,66,0.9) 1%, rgba(2,25,65,0.5) 99%);
    border-radius: 5px 5px 5px 5px;
    border: 1px solid;
    border-image: linear-gradient(180deg, rgba(0, 228, 236, 0.5), rgba(79, 139, 152, 0.1)) 1 1;
    margin-bottom: 10px;
    padding: 20px;
    box-sizing: border-box;
    .introduceRecommend{
      height: calc(100% - 200px);
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
    .introduce{
      display: flex;
    }
    .introduce img{
      width: 16px;
      height: 16px;
      margin-right: 10px;
    }
    .introduce .content{
      font-weight: 400;
      font-size: 14px;
      line-height: 1.8;
      // text-indent: 2em;
      padding: 6px;
      transition: all 0.3s ease;
      background: rgba(89,175,255,0.15);
      border-radius: 3px;
      color: #fff;
    }
    .introduce.content:hover {
      transform: scale(1.02);
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    }

    .recommend,.describe{
      margin-top: 40px;
      .header{
        display: flex;
        justify-content: space-between;
        align-items: center;
        .title{
          font-weight: bold;
          font-size: 16px;
          color: #42D9FF;
          display: flex;
          align-items: center;
          gap: 5px;
        }
      }
      .content{
        display: flex;
        margin-top: 20px;
        width: 100%;
        justify-content: space-between;
        .row{
          width: 23%;
          img{
            width: 100%;
            height: 120px;
            border-radius: 16px;
            border: 2px solid #3B80FF;
          }
          .title{
            font-weight: 500;
            font-size: 13px;
            color: #fff;
            margin: 10px 0;
          }
          .desc{
            font-weight: 400;
            text-align: left;
            font-size: 14px;
            color: rgba(255, 255, 255, 0.7);
            line-height: 24px;
            margin-bottom: 6px;
          }
        }
      }
    }
    .recommend{
      margin-top: 10px;
      .content{
        display: block;
        .row{
          width: 100%;
          cursor: pointer;
        }
      }
    }
  }
   // 图片预览样式 - 内联显示
  .image-preview-inline {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 10px;
    border-radius: 8px;
    .image-item {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
      width: 80px;
      height: 80px;
      img {
        width: 80px;
        height: 80px;
        object-fit: cover;
        border-radius: 4px;
      }
      .image-actions {
        position: absolute;
        right: 0;
        background: #bbb6b6;
        border-radius: 10px;
        color: #fff;
        font-size: 10px;
        padding: 4px;
        cursor: pointer;
      }
    }
  }
  // 输入框
  .input-container{
      width: 100%;
      min-height: 200px;
      background: linear-gradient( 180deg, rgba(2,25,66,0.9) 1%, rgba(2,25,65,0.5) 99%);
      border-radius: 5px 5px 5px 5px;
      border: 1px solid;
      border-image: linear-gradient(180deg, rgba(0, 228, 236, 0.5), rgba(79, 139, 152, 0.1)) 1 1;
      position: absolute;
      bottom: 0;
      :deep(.el-textarea__inner){
        box-shadow: none;
        border-radius: 5px;
        background: transparent;
      }
      .input-actions{
        display: flex;
        gap: 10px;
        justify-content: flex-end;
        position: absolute;
        right: 10px;
        bottom: 0;
        .button{
          width: 24px;
          height: 24px;
          line-height: 36px;
          cursor: pointer;
        }
        .button .loading{
          color: #fff;
          animation: rotate 2s linear infinite;
        }
        .button:last-child{
          &:hover {
            transform: scale(1.05);
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
          }
        }
      }
    }
}
// 定义旋转动画
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>