<!-- 检测测试主界面组件 -->
<template>
  <div>
    <!-- 主检测界面 -->
    <div class='dialog' v-bind='dialogBig'>
      <!-- 标题栏：显示时间、进度条、日志按钮 -->
      <div class='dialog-title'>
        <!-- 检测用时显示 -->
        <div class='timeView'>
          <el-icon style='margin: 0px 5px;'>
            <Clock />
          </el-icon>
          <span>检测用时：{{ timeView }}</span>
        </div>
        <!-- 检测进度条 -->
        <el-progress
          style='width: 82%; margin-right: 3%;'
          :percentage='percentage'
          :color='customColors' />
        <!-- 检测项进度按钮 -->
        <el-button style='width: 10%' type='text' :icon='InfoFilled' @click='showTestLog'>检测项进度</el-button>
      </div>

      <!-- 检测结果表格内容区 -->
      <div class='dialog-content'>
        <!-- 检测结果表格 -->
        <el-table :data='checkResultView' row-key='scriptType' height='450px'
                  :header-cell-style="{ background: 'var(--el-color-primary)', color: '#eee', textAlign: 'center' } "
                  style='width: 100%'
                  border>
          <!-- 固定列：检测项目名称 -->
          <el-table-column fixed prop='scriptName' label='检测项目' width='150px' align='center'>
          </el-table-column>

          <!-- 动态列：当通道数不超过最大限制时显示详细通道 -->
          <template v-if='chnSum<=MAX_CHN_SUM'>
            <!-- 遍历设备列表 -->
            <el-table-column v-for='(item,index1) in deviceList' :key='item.deviceId' :label='item.deviceName'
                             :min-width='110' align='center'>
              <!-- 遍历每个设备的通道 -->
              <el-table-column v-for='(chnItem,index2) in item.chnNum' :key='`${item.deviceId}${chnItem}`'
                               :label="'通道'+chnItem" align='center'>
                <template #default='{row}'>
                  <!-- 通道状态提示 -->
                  <el-tooltip
                    :content="row.devices[index1].chnResult[index2].icon==='More'?'暂无数据'
                      :row.devices[index1].chnResult[index2].icon==='CircleCheckFilled'?'符合'
                      :row.devices[index1].chnResult[index2].icon==='Close'?'不符合'
                      :row.devices[index1].chnResult[index2].icon==='WarnTriangleFilled'?'数据异常'
                      :row.devices[index1].chnResult[index2].icon==='Loading'?'检测中':'连接中断'"
                    placement='right'>
                    <!-- 通道状态按钮 -->
                    <el-button
                      :disabled='row.devices[index1].chnResult[index2].color===CheckData.ButtonColorEnum.INFO || row.devices[index1].chnResult[index2].color===CheckData.ButtonColorEnum.LOADING'
                      :color='row.devices[index1].chnResult[index2].color'
                      size='small'
                      @click='handleClick(item,chnItem,row.scriptType)'
                      style='align-self: center;'
                    >
                      <!-- 加载状态图标 -->
                      <el-icon v-if="row.devices[index1].chnResult[index2].icon==='Loading'" class='loading-box'
                               style='color: #fff'>
                        <component :is='Loading' />
                      </el-icon>
                      <!-- 其他状态图标 -->
                      <el-icon v-else style='color: #fff'>
                        <component :is='row.devices[index1].chnResult[index2].icon' />
                      </el-icon>
                    </el-button>

                  </el-tooltip>
                </template>
              </el-table-column>
            </el-table-column>
          </template>


        </el-table>
      </div>

    </div>
    <!-- 检测日志抽屉容器 -->
    <div class='drawer-container'>
      <!-- 从下往上弹出的检测日志抽屉 -->
      <el-drawer v-model='drawer' title='检测项进度' direction='btt' :size="'38%'">
        <!-- 日志内容滚动容器 -->
        <div ref='scrollContainerRef' style='height: 100%; overflow-y: auto;'>
          <!-- 日志列表，根据类型显示不同颜色 -->
          <p v-for='(item, index) in testLogList'
             :key='index'
             :style="{color:item.type==='error'?'#F56C6C':item.type==='warning'?'#e6a23c':'var(--el-text-color-regular)'}">
            {{ item.log }}<br />
          </p>
        </div>
      </el-drawer>
    </div>

    <!-- 单通道单测试项详情弹窗 -->
    <dataCheckSingleChannelSingleTestPopup ref='dataCheckSingleChannelSingleTestPopupRef' />
  </div>
</template>
<script lang='tsx' setup name='test'>
// Element Plus 图标导入
import { InfoFilled, Loading } from '@element-plus/icons-vue'
// 单通道单测试项详情弹窗组件
import dataCheckSingleChannelSingleTestPopup from './dataCheckSingleChannelSingleTestPopup.vue'
// Vue 3 Composition API
import { computed, reactive, ref, toRef, watch } from 'vue'
// 对话框大小绑定工具
import { dialogBig } from '@/utils/elementBind'
// 检测数据类型定义
import { CheckData } from '@/api/check/interface'
// 检测相关状态管理
import { useCheckStore } from '@/stores/modules/check'
// Element Plus 消息组件
import { ElMessage, ElMessageBox } from 'element-plus'
// 检测相关API
import { getBigTestItem } from '@/api/check/test'
import { getAutoGenerate } from '@/api/user/login'
import { generateDevReport } from '@/api/plan/plan'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useDictStore } from '@/stores/modules/dict'

// 获取检测状态管理实例
const checkStore = useCheckStore()
const modeStore = useModeStore()
const dictStore = useDictStore()
// 最大通道数限制，超过此数量将使用汇总显示
const MAX_CHN_SUM = 12

// 总测试项数
let checkTotal = 0

// 组件属性定义
const props = defineProps({
  // 测试状态：waiting/start/process/paused/success等
  testStatus: {
    type: String,
    default: 'waiting',
  },
  // 当前步骤索引
  stepsActive: {
    type: Number,
  },
  // WebSocket消息数据
  webMsgSend: {
    type: Object,
    default: () => ({}),
  },
})

// 定义向父组件发送的事件
const emit = defineEmits(['update:testStatus', 'update:webMsgSend', 'sendPause', 'sendResume', 'closeWebSocket'])

// ========== 界面状态相关 ==========
// 测试项进度抽屉是否打开
const drawer = ref(false)
// 进度条颜色配置
const customColors = [{ color: '#91cc75', percentage: 100 }]

// ========== 检测数据相关 ==========
// 检测脚本配置数据
let scriptData: CheckData.ScriptItem[] = []
// 被检测的设备列表
const deviceList = reactive<CheckData.Device[]>([])
// 当前正在执行的测试项索引
let activeIndex = 0
// 检测进度百分比
const percentage = ref(0)

// ========== 时间计算相关 ==========
// 定时器实例
let timer: any = null
// 总计时秒数
const timeCount = ref(0)
// 格式化的时间显示（HH:MM:SS）
const timeView = ref('00:00:00')
// 测试项开始检测时间（或继续检测时间）
const startData = ref(new Date())
// 测试项检测结束时间（或暂停时的时间）
const endData = ref(new Date())
// 累计时间差（毫秒）
const timeDifference = ref(0)

// ========== 检测结果相关 ==========
// 详细检测结果数据（详细到每个设备的每个通道）
const checkResult = reactive<CheckData.ScriptChnItem[]>([])
// 存储检测失败的测试项信息（只要有一个通道不合格，该测试项就被记录）
let errorCheckItem: Array<{ scriptType: string, type: CheckData.ChnCheckResultEnum }> = []
// 检测日志列表
const testLogList = reactive<CheckData.LogItem[]>([{ type: 'info', log: '暂无数据，等待检测开始' }])

// ========== 响应式引用 ==========
// 将props转为ref，便于watch监听
const testStatus = toRef(props, 'testStatus')
const webMsgSend = toRef(props, 'webMsgSend')

// ========== DOM引用 ==========
// 日志滚动容器引用
const scrollContainerRef = ref()
// 单通道单测试项详情弹窗组件引用
const dataCheckSingleChannelSingleTestPopupRef = ref<InstanceType<typeof dataCheckSingleChannelSingleTestPopup>>()

// ========== 计算属性 ==========
// 计算所有设备的总通道数
const chnSum = computed(() => {
  let sum = 0
  deviceList.forEach((item) => {
    sum += item.chnNum
  })
  return sum
})

// 将原始检测结果转换为表格展示所需的视图数据
const checkResultView: ComputedRef<CheckData.ScriptChnViewItem[]> = computed(() => {

  let result: CheckData.ScriptChnViewItem[] = checkResult.map(item => {
    let temp: CheckData.ScriptChnViewItem = {
      scriptType: item.scriptType,
      scriptName: item.scriptName,
      devices: [],
    }

    // 遍历每个设备，生成对应的按钮显示数据
    item.devices.forEach(device => {
      let tempChnBtnResult: CheckData.ButtonResult[] = []

      // 只有在总通道数不超过最大限制时，才显示详细通道
      if (chnSum.value <= MAX_CHN_SUM) {
        // 为每个通道生成对应的按钮配置（颜色+图标）
        for (let j = 0; j < device.chnResult.length; j++) {
          switch (device.chnResult[j]) {
            case CheckData.ChnCheckResultEnum.UNKNOWN:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.INFO, icon: 'More' })
              break
            case CheckData.ChnCheckResultEnum.LOADING:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.LOADING, icon: 'Loading' })
              break
            case CheckData.ChnCheckResultEnum.SUCCESS:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.SUCCESS, icon: 'CircleCheckFilled' })
              break
            case CheckData.ChnCheckResultEnum.FAIL:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.DANGER, icon: 'Close' })
              break
            case CheckData.ChnCheckResultEnum.TIMEOUT:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.WARNING, icon: 'Link' })
              break
            case CheckData.ChnCheckResultEnum.ERRORDATA:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.WARNING, icon: 'WarnTriangleFilled' })
              break
            case CheckData.ChnCheckResultEnum.NOT_PART_IN_ERROR:
              tempChnBtnResult.push({ color: CheckData.ButtonColorEnum.INFO, icon: 'Minus' })
              break
            default:
              break
          }
        }
      }

      temp.devices.push({
        deviceId: device.deviceId,
        deviceName: device.deviceName,
        chnResult: tempChnBtnResult,
      })
    })
    return temp
  })

  return result
})

// ========== 监听器 ==========
// 监听测试状态变化
watch(testStatus, function(newValue, oldValue) {
  // 开始测试
  if (newValue == 'start') {
    // 根据测试项配置决定是否需要初始化
    if (!checkStore.selectTestItems.preTest && !checkStore.selectTestItems.channelsTest) {
      ElMessage.success('初始化开始!')
      emit('update:testStatus', 'test_init')
      testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：初始化开始！` })
    } else {
      // 直接进入检测流程
      emit('update:testStatus', 'process')
    }
    // 开始计时
    startTimeCount()
    // 显示测试日志抽屉
    showTestLog()
    // 重置时间记录
    startData.value = new Date()
    timeDifference.value = 0
  }

  // 需要停止计时的状态
  if (newValue == 'recheck' || newValue == 'error' || newValue == 'test_init_fail' || newValue == 'connect_timeout' || newValue == 'pause_timeout' || oldValue == 'error_flow_end') {
    stopTimeCount()
  }
})

// 防重复处理计数器
let count = 0

// 监听WebSocket消息变化，处理各种检测状态和错误
watch(webMsgSend, function(newValue, oldValue) {

  // 只在非等待状态下处理消息
  if (testStatus.value !== 'waiting') {
    // 步骤4：正式检测阶段的消息处理
    if (props.stepsActive === 4) {
      // ========== 初始化错误码处理 ==========
      if (newValue.code == 10520) {
        ElMessageBox.alert('报文解析异常！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：报文解析异常！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10521) {
        ElMessageBox.alert('程控源參数有误！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：程控源參数有误！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10522) {
        ElMessageBox.alert('测试项解析有误！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：测试项解析有误！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10523) {
        if (count === 0) {
          ElMessageBox.alert('源连接失败！', '初始化失败', {
            confirmButtonText: '确定',
            type: 'error',
          })
          testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：源连接失败！` })
          emit('update:testStatus', 'test_init_fail')
          count++
        }
      } else if (newValue.code == 10524) {
        ElMessageBox.alert('获取源控制权失败！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：获取源控制权失败！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10525) {
        ElMessageBox.alert('重置源失败！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：重置源失败！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10527) {
        ElMessageBox.alert('源未进行初始化！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：源未进行初始化！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10528) {
        ElMessageBox.alert('目标源有误(该用户已控制其他源，在关闭前无法操作新的源)！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({
          type: 'error',
          log: `${new Date().toLocaleString()}：目标源有误(该用户已控制其他源，在关闭前无法操作新的源)！`,
        })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10529) {
        ElMessageBox.alert('源状态有误，无法响应报文(例如源处于输出状态，无法响应初始化报文)！', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({
          type: 'error',
          log: `${new Date().toLocaleString()}：源状态有误，无法响应报文(例如源处于输出状态，无法响应初始化报文)！`,
        })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10550) {
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：${newValue.data}设备连接异常！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10551) {
        ElMessageBox.alert(`${newValue.data}设备触发报告异常！`, '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：${newValue.data}设备触发报告异常！` })
        emit('update:testStatus', 'test_init_fail')
      } else if (newValue.code == 10552) {
        ElMessageBox.alert('存在已经初始化步骤,执行自动关闭,请重新发起检测', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        testLogList.push({
          type: 'error',
          log: `${new Date().toLocaleString()}：存在已经初始化步骤,执行自动关闭,请重新发起检测！`,
        })
        emit('update:testStatus', 'test_init_fail')
      } else {
        // ========== 根据请求ID处理不同类型的消息 ==========
        switch (newValue.requestId) {
          // 服务端错误
          case 'server_error':
            if (newValue.operateCode === 'server_error' && count === 0) {
              ElMessageBox.alert('服务端主动关闭连接!', '初始化失败', {
                confirmButtonText: '确定',
                type: 'error',
              })
              testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：服务端主动关闭连接！` })
              emit('update:testStatus', 'test_init_fail')
              count++
            }
            break
          // 设备端错误
          case 'device_error':
            if (newValue.operateCode === 'device_error' && count === 0) {
              ElMessageBox.alert('设备端主动关闭连接!', '初始化失败', {
                confirmButtonText: '确定',
                type: 'error',
              })
              testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：设备端主动关闭连接！` })
              emit('update:testStatus', 'test_init_fail')
              count++
            }
            break
          // 正式测试相关消息
          case 'formal_real':
            switch (newValue.operateCode) {
              case 'stop_timeout':
                ElMessageBox.alert(`暂停时间已过10分钟，本次检测已失效，请重新发起检测！`, '暂停时间过长', {
                  confirmButtonText: '确定',
                  type: 'error',
                })
                emit('update:testStatus', 'pause_timeout')
                break
            }
            break
          case 'error_flow_end':
            ElMessageBox.alert(`当前流程存在异常结束！`, '初始化失败', {
              confirmButtonText: '确定',
              type: 'error',
            })
            emit('update:testStatus', 'test_init_fail')
            break
          case 'socket_timeout':
            ElMessageBox.alert('连接超时！', '连接超时', {
              confirmButtonText: '确定',
              type: 'error',
            })
            emit('update:testStatus', 'connect_timeout')
            break
          case 'connect':
            switch (newValue.operateCode) {
              case 'Source':
                ElMessageBox.alert('源通讯失败，请检查源连接情况！', '初始化失败', {
                  confirmButtonText: '确定',
                  type: 'error',
                })
                testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：源通讯失败！` })
                break
              case 'Dev':
                ElMessageBox.alert('设备通讯失败，请检查设备连接情况！', '初始化失败', {
                  confirmButtonText: '确定',
                  type: 'error',
                })
                testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：设备通讯失败！` })
                break
            }
            emit('update:testStatus', 'test_init_fail')
            break
          // 源通信校验阶段
          case 'yjc_ytxjy':
            switch (newValue.operateCode) {
              case 'INIT_GATHER':
                if (newValue.code == 10200) {
                  testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：源初始化成功！` })
                  percentage.value = 1
                }
                if (newValue.code == -1) {
                  ElMessageBox.alert('源未知异常！', '初始化失败', {
                    confirmButtonText: '确定',
                    type: 'error',
                  })
                  testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：源未知异常！` })
                  emit('update:testStatus', 'test_init_fail')
                }
                break
            }
            break
          // 设备通信校验阶段
          case 'yjc_sbtxjy':
            switch (newValue.operateCode) {
              case 'INIT_GATHER$01':
                if (newValue.code == 25001) {
                  testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：设备通讯校验成功！` })
                  percentage.value = 2
                }
                break
            }
            break
          // 协议校验阶段
          case 'yjc_xyjy':
            switch (newValue.operateCode) {
              case 'VERIFY_MAPPING$01':
                if (newValue.code == 25001) {
                  ElMessage.success('初始化成功!')
                  testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：协议校验成功！` })
                  timeDifference.value = +new Date().getTime() - startData.value.getTime()
                  testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：初始化成功！` })
                  percentage.value = 3
                  // 初始化完成，准备开始正式检测
                  activeIndex = getNextActiveIndex() + 2
                  emit('update:testStatus', 'process')
                } else if (newValue.code == 25002) {
                  let data = JSON.parse(newValue.data)
                  ElMessageBox.alert(`脚本与icd校验失败！icd名称：${data['icdType']} -> 校验项：${data['dataType']}`, '初始化失败', {
                    confirmButtonText: '确定',
                    type: 'error',
                  })
                  testLogList.push({
                    type: 'error',
                    log: `${new Date().toLocaleString()}：脚本与icd校验失败！icd名称：${data['icdType']} -> 校验项：${data['dataType']}`,
                  })
                  emit('update:testStatus', 'test_init_fail')
                } else if (newValue.code == 10500) {
                  ElMessageBox.alert(`装置中未找到该icd！`, '初始化失败', {
                    confirmButtonText: '确定',
                    type: 'error',
                  })
                  testLogList.push({
                    type: 'error',
                    log: `${new Date().toLocaleString()}：装置中未找到该icd！`,
                  })
                  emit('update:testStatus', 'test_init_fail')
                }
                break
            }
            break
          // 暂停测试成功
          case 'preStopTest':
            if (newValue.operateCode == 'stop') {
              ElMessage.success('暂停成功')
              emit('update:testStatus', 'paused')
              pauseSuccessCallback()
            }
            break
          // 继续测试成功
          case 'Resume_Success':
            ElMessage.success('开始继续检测')
            emit('update:testStatus', 'process')
            handleResumeTest()
            break
          // ========== 各类检测项的开始和结束消息处理 ==========
          // 频率检测
          case 'FREQ_Start':
            handleStartItem('FREQ', newValue.desc)
            break
          case 'FREQ_End':
            handleEndItem('FREQ', newValue.desc, newValue.data)
            break
          case 'V_Start':
            handleStartItem('V', newValue.desc)
            break
          case 'V_End':
            handleEndItem('V', newValue.desc, newValue.data)
            break
          case 'P_Start':
            handleStartItem('P', newValue.desc)
            break
          case 'P_End':
            handleEndItem('P', newValue.desc, newValue.data)
            break
          case 'HV_Start':
            handleStartItem('HV', newValue.desc)
            break
          case 'HV_End':
            handleEndItem('HV', newValue.desc, newValue.data)
            break
          case 'HI_Start':
            handleStartItem('HI', newValue.desc)
            break
          case 'HI_End':
            handleEndItem('HI', newValue.desc, newValue.data)
            break
          case 'HP_Start':
            handleStartItem('HP', newValue.desc)
            break
          case 'HP_End':
            handleEndItem('HP', newValue.desc, newValue.data)
            break
          case 'HSV_Start':
            handleStartItem('HSV', newValue.desc)
            break
          case 'HSV_End':
            handleEndItem('HSV', newValue.desc, newValue.data)
            break
          case 'HSI_Start':
            handleStartItem('HSI', newValue.desc)
            break
          case 'HSI_End':
            handleEndItem('HSI', newValue.desc, newValue.data)
            break
          case 'VOLTAGE_Start':
            handleStartItem('VOLTAGE', newValue.desc)
            break
          case 'VOLTAGE_End':
            handleEndItem('VOLTAGE', newValue.desc, newValue.data)
            break
          case 'I_Start':
            handleStartItem('I', newValue.desc)
            break
          case 'I_End':
            handleEndItem('I', newValue.desc, newValue.data)
            break
          case 'IMBV_Start':
            handleStartItem('IMBV', newValue.desc)
            break
          case 'IMBV_End':
            handleEndItem('IMBV', newValue.desc, newValue.data)
            break
          case 'IMBA_Start':
            handleStartItem('IMBA', newValue.desc)
            break
          case 'IMBA_End':
            handleEndItem('IMBA', newValue.desc, newValue.data)
            break
          case 'F_Start':
            handleStartItem('F', newValue.desc)
            break
          case 'F_End':
            handleEndItem('F', newValue.desc, newValue.data)
            break
          // 检测结束
          case 'Quit':
      
            break
        }
      }
    }
  }
}, { deep: true })

// ========== 检测项处理函数 ==========
// 处理检测项开始消息
const handleStartItem = (code: string, desc: string | undefined) => {
  if (desc === undefined) {
    // 大测试项开始
    activeIndex = getActiveIndex(code)
    updateCheckResultView(code, true)  // 更新界面为加载状态
    updateLog(true)                    // 记录开始日志
  } else {
    // 子测试项开始
    testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：${desc}准确度检测：开始` })
  }
}

// 处理检测项结束消息
const handleEndItem = (code: string, desc: string | undefined, devices: CheckData.DeviceCheckResult[] = []) => {
  if (desc === undefined) {
    // 大测试项结束
    updatePercentage()                        // 更新进度
    updateCheckResultView(code, false, devices) // 更新检测结果
    updateLog(false)                          // 记录结束日志
    if (testStatus.value != 'paused') {
      // 如果未暂停，继续下一个测试项
      activeIndex = getNextActiveIndex(code)
    }
  } else {
    // 子测试项结束，根据结果记录不同类型的日志
    let result = getResult(devices)
    if (result === 1) {
      testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：${desc}检测结束：符合` })
    }
    if (result === 2) {
      testLogList.push({ type: 'error', log: `${new Date().toLocaleString()}：${desc}检测结束：不符合` })
    }
    if (result === 4) {
      testLogList.push({ type: 'warning', log: `${new Date().toLocaleString()}：${desc}检测结束：数据异常` })
    }
  }
}

// 更新检测进度
const updatePercentage = async () => {
  if (activeIndex < checkTotal) {
    // 计算并更新进度百分比
    percentage.value = Math.trunc(activeIndex / checkTotal * 100)
  } else {
    // 所有检测项完成
    percentage.value = 100
    // 先完成所有后续操作，再emit success
    try {
      // 检查是否需要自动生成报告
      let { data: autoGenerate } = await getAutoGenerate()
      if (autoGenerate == 1) {
        // 自动生成报告
        let devIdList = checkStore.devices.map(item => {
          return item.deviceId
        })
        await generateDevReport({
          'planId': checkStore.plan.id,
          'devIdList': devIdList,
          'scriptId': checkStore.plan.scriptId,
          'planCode': checkStore.plan.code + ''
        })
      }
      // 提示检测完成
      await ElMessageBox.alert('检测全部结束,你可以停留在此页面查看检测结果，或返回首页进行复检、报告生成和归档等操作', '检测完成', {
        confirmButtonText: '确定',
      })
      // 关闭WebSocket连接
      emit('closeWebSocket')
    } finally {
      // 最后才emit success，避免中断后续操作
      emit('update:testStatus', 'success')
    }
  }
}

// ========== 生命周期钩子 ==========
// 组件挂载前初始化数据
onBeforeMount(async () => {
  await initScriptData()  // 获取检测脚本配置
  initDeviceList()        // 初始化设备列表
  initCheckResult()       // 初始化检测结果数据结构
})

// ========== 界面交互函数 ==========
// 显示测试日志抽屉
const showTestLog = () => {
  drawer.value = true
}

// ========== 数据初始化函数 ==========
// 从服务器获取检测脚本配置数据
const initScriptData = async () => {
  const pattern = dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '';
  // 根据复检类型、计划ID、设备ID列表获取测试项
  let response: any = await getBigTestItem({
    reCheckType: checkStore.reCheckType,
    planId: checkStore.plan.id,
    devIds: checkStore.devices.map(item => item.deviceId),
    patternId: pattern
  })

  // 格式化脚本数据
  let temp = response.data.map((item: any) => {
    return {
      ...item,
      scriptName: item.scriptName,
    }
  })

  // 保存脚本数据并设置总数
  scriptData.push(...temp)
  checkTotal = scriptData.length
}

// 从store中获取设备列表数据
const initDeviceList = () => {
  Object.assign(deviceList, checkStore.devices)
}

// 初始化检测结果数据结构（每个测试项的每个设备的每个通道）
const initCheckResult = () => {
  let result: CheckData.ScriptChnItem[] = []

  // 为每个检测脚本创建结果数据结构
  scriptData.forEach(item => {
    let temp: CheckData.ScriptChnItem = {
      scriptType: item.id,
      scriptName: item.scriptName,
      devices: [],
    }

    // 为每个设备创建通道结果
    for (let i = 0; i < deviceList?.length; i++) {
      let tempChnResult: CheckData.ChnCheckResultEnum[] = []
      // 初始化所有通道状态为UNKNOWN
      for (let j = 0; j < deviceList[i].chnNum; j++) {
        tempChnResult.push(CheckData.ChnCheckResultEnum.UNKNOWN)
      }
      temp.devices.push({
        deviceId: deviceList[i].deviceId,
        deviceName: deviceList[i].deviceName,
        chnResult: tempChnResult,
      })
    }
    result.push(temp)
  })
  Object.assign(checkResult, result)
}

// ========== 数据更新函数 ==========
// 更新指定测试项的检测结果
const updateCheckResult = (data: CheckData.ScriptChnItem) => {
  const { scriptType } = { ...data }

  // 找到对应的测试项并更新其结果
  checkResult.forEach(item => {
    if (item.scriptType == scriptType) {
      // 更新每个设备的通道结果
      for (let i = 0; i < item.devices.length; i++) {
        let targetDevice = data.devices.find(dev => dev.deviceId === item.devices[i].deviceId)
        if (targetDevice !== undefined) {
          // 深拷贝结果数据
          item.devices[i].chnResult = [...targetDevice.chnResult]
        }
      }
    }
  })
}

// 滚动日志到底部
const scrollToBottom = () => {
  if (scrollContainerRef.value) {
  setTimeout(() => {
      scrollContainerRef.value.scrollTop = scrollContainerRef.value.scrollHeight + 70
  },10)
  }
}

// ========== 工具函数 ==========
// 生成随机整数（0到max-1）
function getRandomInt(max: number): number {
  return Math.floor(Math.random() * max)
}


// 将毫秒时间差转换为可读的时间格式
function getTimeDifference(timeDifference: number): string {
  // 时间单位常量
  const millisecondsPerDay = 1000 * 60 * 60 * 24
  const millisecondsPerHour = 1000 * 60 * 60
  const millisecondsPerMinute = 1000 * 60
  const millisecondsPerSecond = 1000

  // 计算各时间单位的值
  const days = Math.floor(timeDifference / millisecondsPerDay)
  const hours = Math.floor((timeDifference % millisecondsPerDay) / millisecondsPerHour)
  const minutes = Math.floor((timeDifference % millisecondsPerHour) / millisecondsPerMinute)
  const seconds = Math.floor((timeDifference % millisecondsPerMinute) / millisecondsPerSecond)

  // 根据时间长度返回合适的格式
  if (days > 0) {
    return `: ${days} 天, ${hours} 小时, ${minutes} 分钟, ${seconds} 秒`
  } else if (hours > 0) {
    return `: ${hours} 小时, ${minutes} 分钟, ${seconds} 秒`
  } else {
    return `: ${minutes} 分钟, ${seconds} 秒`
  }
}

// 监听日志列表变化，自动滚动到底部
watch(testLogList, () => {
  scrollToBottom()
}, { deep: true })

// ========== 日志记录函数 ==========
// 更新检测日志（记录检测项的开始和结束）
const updateLog = (isStart: boolean) => {
  const currentTime = ref(new Date().toLocaleString())
  let timeDifferenceItem = 0

  // 确保在有效的测试项范围内
  if (activeIndex <= checkTotal) {
    if (isStart) {
      // 记录测试项开始
      startData.value = new Date()
      testLogList.push({
        type: 'info',
        log: currentTime.value + ` ：${scriptData[activeIndex - 1].scriptName}准确度检测：开始`,
      })
    } else {
      // 记录测试项结束
      endData.value = new Date()
      timeDifferenceItem = endData.value.getTime() - startData.value.getTime()
      timeDifference.value += timeDifferenceItem

      // 根据检测结果记录不同类型的日志
      let errorItem = getErrorCheckItem(scriptData[activeIndex - 1].id)
      switch (errorItem?.type) {
        case CheckData.ChnCheckResultEnum.SUCCESS:
          testLogList.push({
            type: 'info',
            log: currentTime.value + ` ：${scriptData[activeIndex - 1].scriptName}准确度检测结束：符合，用时` + getTimeDifference(timeDifferenceItem),
          })
          break
        case CheckData.ChnCheckResultEnum.FAIL:
          testLogList.push({
            type: 'error',
            log: currentTime.value + ` ：${scriptData[activeIndex - 1].scriptName}准确度检测结束：不符合，用时` + getTimeDifference(timeDifferenceItem),
          })
          break
        case CheckData.ChnCheckResultEnum.TIMEOUT:
          testLogList.push({
            type: 'warning',
            log: currentTime.value + ` ：${scriptData[activeIndex - 1].scriptName}准确度检测结束：连接超时，用时` + getTimeDifference(timeDifferenceItem),
          })
          break
        case CheckData.ChnCheckResultEnum.ERRORDATA:
          testLogList.push({
            type: 'warning',
            log: currentTime.value + ` ：${scriptData[activeIndex - 1].scriptName}准确度检测结束：数据异常，用时` + getTimeDifference(timeDifferenceItem),
          })
          break
      }

      // 更新总时间显示
      timeView.value = secondToTime(timeDifference.value / 1000)
      // 如果是最后一个测试项，记录总结日志
      if (activeIndex === checkTotal) {
        testLogList.push({
          type: 'info',
          log: currentTime.value + ' ：检测结束，总用时' + getTimeDifference(timeDifference.value),
        })
        stopTimeCount()
      }
    }
  }
}

// ========== 错误处理函数 ==========
// 设置测试项错误状态（分析所有通道结果，确定整体状态）
const setErrorCheckItem = (scriptType: string, devices: CheckData.DeviceCheckResult[]) => {
  let type = 1  // 默认为成功
  let tempChnResult: CheckData.ChnCheckResultEnum[] = []

  // 收集所有设备所有通道的结果
  for (let i = 0; i < devices.length; i++) {
    tempChnResult.push(...devices[i].chnResult)
  }

  // 按优先级确定整体状态（数据异常 > 失败 > 超时）
  if (tempChnResult.some(item => item === CheckData.ChnCheckResultEnum.ERRORDATA)) {
    type = CheckData.ChnCheckResultEnum.ERRORDATA
  }
  if (tempChnResult.some(item => item === CheckData.ChnCheckResultEnum.FAIL)) {
    type = CheckData.ChnCheckResultEnum.FAIL
  }
  if (tempChnResult.some(item => item === CheckData.ChnCheckResultEnum.TIMEOUT)) {
    type = CheckData.ChnCheckResultEnum.TIMEOUT
    // 处理超时情况：记录日志并弹出提示
    for (let i = 0; i < devices.length; i++) {
      if (devices[i].chnResult.some(item => item === CheckData.ChnCheckResultEnum.TIMEOUT)) {
        testLogList.push({
          type: 'warning',
          log: `${new Date().toLocaleString()} ：${devices[i].deviceName}连接超时`,
        })
        ElMessageBox.alert('连接超时！', '连接超时', {
          confirmButtonText: '确定',
          type: 'error',
        })
        emit('update:testStatus', 'connect_timeout')
      }
    }
  }

  // 记录测试项的错误状态
  errorCheckItem.push({ scriptType, type: type })
}

// 获取指定测试项的错误状态
// 判断该检测项是否全部合格（所有设备所有通道所有子检测项目全部合格为合格，否则为不合格）
function getErrorCheckItem(scriptType: string) {
  let results = errorCheckItem.filter((item) => item.scriptType === scriptType)
  if (results.length > 0) {
    return results[0]
  } else {
    return null
  }
}

// 更新检测结果视图
const updateCheckResultView = (scriptCode: string, isStart: boolean, devices: CheckData.DeviceCheckResult[] = []) => {
  // 根据代码找到对应的测试项ID
  let scriptType = scriptData.filter(item => item.code === scriptCode)[0]?.id
  let temp = null

  if (isStart) {
    // 开始时设置为加载状态
    temp = getLoadingResult(scriptType)
  } else {
    // 结束时设置实际结果并记录错误状态
    setErrorCheckItem(scriptType, devices)
    temp = {
      scriptType,
      devices,
    }
  }
  updateCheckResult(temp)
}

// 生成加载状态的结果数据（所有通道显示为正在检测）
const getLoadingResult = (scriptType: string) => {
  let devices = []

  // 为每个设备的每个通道设置LOADING状态
  devices = deviceList.map(item => {
    let tempChnResult: CheckData.ChnCheckResultEnum[] = []
    for (let i = 0; i < item.chnNum; i++) {
      tempChnResult.push(CheckData.ChnCheckResultEnum.LOADING)
    }

    return {
      deviceId: item.deviceId,
      deviceName: item.deviceName,
      chnResult: tempChnResult,
    }
  })

  let tempScriptChnItem: CheckData.ScriptChnItem = {
    scriptType,
    devices,
  }

  return tempScriptChnItem
}

// 分析设备检测结果，返回整体状态
const getResult = (devices: CheckData.DeviceCheckResult[] = []) => {
  let type = 1  // 默认成功
  let tempChnResult: CheckData.ChnCheckResultEnum[] = []

  // 收集所有设备的所有通道结果
  for (let i = 0; i < devices.length; i++) {
    tempChnResult.push(...devices[i].chnResult)
  }

  // 按优先级确定结果类型（数据异常 > 失败）
  if (tempChnResult.some(item => item === CheckData.ChnCheckResultEnum.ERRORDATA)) {
    type = CheckData.ChnCheckResultEnum.ERRORDATA
  }
  if (tempChnResult.some(item => item === CheckData.ChnCheckResultEnum.FAIL)) {
    type = CheckData.ChnCheckResultEnum.FAIL
  }
  return type
}

// ========== 事件处理函数 ==========
// 点击通道按钮，查看检测详情
// 参数：设备信息，通道号（-1代表查看全部通道），测试项类型
const handleClick = (item: any, chnNum: number, scriptType: string) => {
  // 查找对应的检测结果
  let checkResultItem = checkResult.find(obj => obj.scriptType === scriptType)
  let flag = -1  // -1:正常, 0:超时, 1:数据异常

  if (checkResultItem) {
    let device = checkResultItem.devices.find(obj => obj.deviceId === item.deviceId)
    if (device) {
      let chnResult = device.chnResult
      if (chnNum === -1) {
        // 查看全部通道的状态
        if (chnResult.findIndex(obj => obj === CheckData.ChnCheckResultEnum.TIMEOUT) !== -1) {
          flag = 0
        }
        if (chnResult.findIndex(obj => obj === CheckData.ChnCheckResultEnum.ERRORDATA) !== -1) {
          flag = 1
        }
      } else {
        // 查看特定通道的状态
        if (chnResult[chnNum - 1] === CheckData.ChnCheckResultEnum.TIMEOUT) {
          flag = 0
        }
        if (chnResult[chnNum - 1] === CheckData.ChnCheckResultEnum.ERRORDATA) {
          flag = 1
        }
      }
    }
  }

  // 根据状态进行不同处理
  if (flag === 0) {
    // 超时状态：显示提示信息
    ElMessageBox.alert('连接超时，请检查设备通讯是否正常', '连接超时', {
      confirmButtonText: '确定',
      type: 'warning',
    })
  }
  if (flag === -1 || flag === 1) {
    // 正常或数据异常：打开详情弹窗
    checkStore.setShowDetailType(2)
    dataCheckSingleChannelSingleTestPopupRef.value?.open(item.deviceId, chnNum + '', scriptType)
  }
}

// ========== 暂停/继续相关函数 ==========
// 处理暂停请求
const handlePause = () => {
  testLogList.push({
    type: 'error',
    log: `${new Date().toLocaleString()}：当前测试小项正在执行中，将在该小项执行结束后暂停...`,
  })
}

// 暂停成功回调
const pauseSuccessCallback = () => {
  // 记录暂停时的时间
  endData.value = new Date()
  let diffTime = endData.value.getTime() - startData.value.getTime()
  timeDifference.value += diffTime

  // 记录暂停日志
  testLogList.push({
    type: 'info',
    log: `${new Date().toLocaleString()}：暂停检测`,
  })
  stopTimeCount()

}


// 处理继续检测
const handleResumeTest = () => {
  // 重新开始计时
  startData.value = new Date()
  testLogList.push({ type: 'info', log: `${new Date().toLocaleString()}：开始重新检测！` })
  resumeTimeCount()
 
}

// ========== 测试项索引管理函数 ==========
// 根据测试项代码获取对应的索引号（从1开始）
const getActiveIndex = (code: string): number => {
  for (let i = 0; i < scriptData.length; i++) {
    if (scriptData[i].code === code) {
      return i + 1
    }
  }
  return -1
}

// 根据当前测试项代码获取下一个测试项的索引号
const getNextActiveIndex = (code: string = ''): number => {
  if (code === '') {
    return -1
  }
  for (let i = 0; i < scriptData.length; i++) {
    if (scriptData[i].code === code) {
      return i + 2  // 下一个测试项索引
    }
  }
  return -1
}
// ========== 时间计数器管理函数 ==========
// 开始计时
const startTimeCount = () => {
  if (!timer) {
    timer = setInterval(() => {
      timeCount.value = timeCount.value + 1
      timeView.value = secondToTime(timeCount.value)
    }, 1000)
  }
}

// 停止计时
const stopTimeCount = () => {
  if (timer) {
    clearInterval(timer)
    timer = null
  }
}


// 恢复计时（用于暂停后继续）
const resumeTimeCount = () => {
  timer = setInterval(() => {
    timeCount.value = timeCount.value + 1
    timeView.value = secondToTime(timeCount.value)
  }, 1000)
}


// 将秒数转换为 HH:MM:SS 格式
const secondToTime = (second: number) => {
  let h: string | number = Math.floor(second / 3600)  // 小时
  let m: string | number = Math.floor((second - h * 3600) / 60)  // 分钟
  let s: string | number = Math.floor(second % 60)  // 秒

  // 补齐前导零
  h = h < 10 ? '0' + h : h
  m = m < 10 ? '0' + m : m
  s = s < 10 ? '0' + s : s
  return h + ':' + m + ':' + s
}

// 组件卸载前清理定时器和响应式引用
onBeforeUnmount(() => {
  // 清理定时器
  if (timer) {
    clearInterval(timer)
    timer = null
  }
  
  // 清理响应式数组引用，防止内存泄漏
  deviceList.splice(0)
  checkResult.splice(0)
  testLogList.splice(0)
  errorCheckItem.splice(0)
  
  // 重置其他状态
  scriptData.splice(0)
  activeIndex = 0
  checkTotal = 0
  count = 0
})

// 暴露给父组件的方法
defineExpose({
  handlePause,  // 暂停方法
})
</script>

<!-- ========== 样式定义 ========== -->
<style scoped lang='scss'>

/* 表格样式 */
:deep(.el-table .header-row) {
  background-color: #f5f7fa;
}

:deep(.el-table .warning-row) {
  color: red;
}

.el-table .success-row {
  --el-table-tr-bg-color: var(--el-color-success-light-9);
}

/* 主对话框容器 */
.dialog {
  display: flex;
  flex-direction: column;
  overflow-y: hidden;
  overflow-x: hidden;
}

/* 对话框标题栏 */
.dialog-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-right: 10px;
  margin-bottom: 10px;

  /* 时间显示区域 */
  .timeView {
    display: flex;
    align-items: center;
    color: #91cc75;
    width: 28%;
    margin-right: 0px;
    text-align: left;
    font-size: 26px;
    font-weight: bold;
  }
}

/* 对话框内容区 */
.dialog-content {
  max-height: 450px;
  overflow-y: hidden;
}

/* 折叠面板头部样式 */
:deep(.el-collapse-item__header) {
  height: 30px;
}

/* 日志显示区域 */
.dialog-log {
  height: 50px;
  overflow-y: hidden;

  p {
    margin: 5px 0;
    font-size: 14px;
  }
}

/* 抽屉容器样式 */
.drawer-container {
  :deep(header.el-drawer__header) {
    color: #fff !important;
    background-color: var(--el-color-primary) !important;

    .el-drawer__close-btn svg:hover {
      color: #ccc !important;
    }

    .el-drawer__title {
      color: #fff !important;
    }
  }
}

/* 加载动画样式 */
.loading-box {
  animation: loading 1.5s linear infinite;
}

@keyframes loading {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

</style>

<style lang='scss' scoped>
/* 表格按钮样式 */
:deep(.el-button--small) {
  height: 20px !important;
  width: 20px !important;
}

/* 表格单元格内边距 */
:deep(.el-table--default  td ) {
  padding: 5px 0 !important;
}

</style>
