<template>
  <!-- 检测流程弹窗容器 -->
  <el-dialog :title='dialogTitle' width='1550px' :model-value='dialogVisible' :before-close='beforeClose'
             @close='handleClose' height='1000px' draggable>

    <!-- 步骤指示器容器 -->
    <div class='steps-container'>
      <!-- 检测步骤进度条，根据选择的检测项动态显示步骤 -->
      <!-- 注意：Element Plus的active属性从0开始，但业务逻辑从1开始，所以需要减1 -->
      <el-steps v-if='showSteps' class='test-head-steps' simple :active='stepsActiveIndex - 1' process-status='finish'
                finish-status='success'>
        <!-- 预检测步骤 -->
        <el-step v-if='preTestSelected' title='预检测'
                 :icon='stepsActive > 1 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Edit'
                 @click='handleStepClick(1)' />
        <!-- 守时检测步骤 -->
        <el-step v-if='timeTestSelected' title='守时检测'
                 :icon='stepsActive > 2 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :UploadFilled'
                 @click='handleStepClick(2)' />
        <!-- 系数校准步骤 -->
        <el-step v-if='channelsTestSelected' title='系数校准'
                 :icon='stepsActive > 3 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Odometer'
                 @click='handleStepClick(3)' />
        <!-- 正式检测步骤 -->
        <el-step v-if='testSelected' title='正式检测'
                 :icon='stepsActive > 4 || stepsActiveIndex > stepsTotalNum-1? SuccessFilled :Coin'
                 @click='handleStepClick(4)' />
        <!-- 检测完成步骤 -->
        <el-step title='检测完成' :icon='stepsActiveIndex > stepsTotalNum-1 ? SuccessFilled :Key' />
      </el-steps>
    </div>

    <!-- 检测组件容器 - 根据当前步骤显示对应的检测组件 -->
    <!-- 预检测组件 -->
    <preTest v-if='showComponent&&preTestSelected' v-show='preTestSelected && stepsActiveView==1' ref='preTestRef'
             v-model:testStatus='preTestStatus'
             :webMsgSend='webMsgSend' />
    <!-- 守时检测组件 -->
    <timeTest v-if='showComponent&&timeTestSelected' v-show='timeTestSelected && stepsActiveView==2'
              v-model:testStatus='timeTestStatus' />
    <!-- 系数校准检测组件 -->
    <factorTest v-if='showComponent&&channelsTestSelected' v-show='channelsTestSelected && stepsActiveView==3'
                v-model:testStatus='channelsTestStatus'
                :webMsgSend='webMsgSend' />
    <!-- 正式检测组件 -->
    <test v-if='showComponent&&testSelected' ref='testRef' v-show='testSelected && stepsActiveView==4'
          v-model:testStatus='TestStatus' :webMsgSend='webMsgSend'
          @update:webMsgSend='webMsgSend=$event' @sendPause='sendPause' @sendResume='sendResume'
          @closeWebSocket='closeWebSocket'
          :stepsActive='stepsActive' />

    <!-- 弹窗底部操作按钮区域 -->
    <template #footer>
      <div>

        <!-- 开始检测按钮 - 当前状态为等待时显示 -->
        <el-button type='primary' :icon='VideoPlay' v-if="ActiveStatue === 'waiting'" @click='handleSubmitFast'>
          开始检测
        </el-button>

        <!-- 初始化中按钮 - 禁用状态，显示加载动画 -->
        <el-button type='primary' v-if="TestStatus === 'test_init'" disabled>
          <el-icon class='loading-box' style='color: #fff;margin-right: 8px;'>
            <component :is='Refresh' />
          </el-icon>
          初始化中
        </el-button>

        <!-- 停止检测按钮 - 检测进行中时显示 -->
        <el-button
          type='primary'
          v-if="TestStatus=='process'"
          :icon='VideoPause'
          @click='handlePause()'>停止检测
        </el-button>

        <!-- 暂停中按钮 - 禁用状态，显示加载动画 -->
        <el-button type='warning' v-if="TestStatus === 'paused_ing'" disabled>
          <el-icon class='loading-box' style='color: #fff;margin-right: 8px;'>
            <component :is='Refresh' />
          </el-icon>
          暂停中
        </el-button>

        <!-- 继续检测按钮 - 检测已暂停时显示 -->
        <el-button
          type='warning'
          v-if="(TestStatus =='paused')"
          :icon='VideoPlay'
          @click='sendResume'
        >继续检测
        </el-button>

        <!-- 下一步/完成/错误状态按钮 -->
        <el-button :type="ActiveStatue==='success'?'primary':'danger'" :icon='Right'
                   v-if="nextStepText !== '下一步' && (ActiveStatue === 'success'||ActiveStatue==='error'||ActiveStatue==='connect_timeout'||ActiveStatue==='pause_timeout')"
                   @click='nextStep'>
          {{ nextStepText }}
        </el-button>

        <!-- 退出检测按钮 - 默认显示 -->
        <el-button type='primary' @click='handleQuit' v-else>
          退出检测
        </el-button>
      </div>
    </template>
  </el-dialog>


</template>

<script lang='tsx' setup name='testPopup'>
// ====================== 导入依赖 ======================
import { reactive, ref, watch, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  Coin,
  Edit,
  Key,
  Odometer,
  Refresh,
  Right,
  SuccessFilled,
  UploadFilled,
  VideoPause,
  VideoPlay,
} from '@element-plus/icons-vue'
import preTest from './preTest.vue'
import timeTest from './timeTest.vue'
import factorTest from './factorTest.vue'
import test from './test.vue'
import socketClient from '@/utils/webSocketClient'
import { useCheckStore } from '@/stores/modules/check'
import { pauseTest, resumeTest, startPreTest } from '@/api/socket/socket'
import { useUserStore } from '@/stores/modules/user'
import { JwtUtil } from '@/utils/jwtUtil'

// ====================== 状态管理 ======================
const userStore = useUserStore()
const checkStore = useCheckStore()

// ====================== 基础状态变量 ======================
const nextStepText = ref('下一步') // 下一步按钮文本
const dialogVisible = ref(false) // 弹窗显示状态
const dialogTitle = ref('') // 弹窗标题
const showComponent = ref(true) // 是否显示检测组件
const preTestRef = ref(null) // 预检测组件引用
const testRef = ref(null) // 正式检测组件引用

// ====================== 步骤控制相关变量 ======================
const showSteps = ref(false) // 是否显示步骤条
const stepsTotalNum = ref(-1) // 步骤总数（选中的检测项数量 + 1个完成步骤）
const stepsActiveIndex = ref(1) // 当前正在执行的步骤索引（用于UI显示高亮）
const stepsActiveView = ref(-1) // 当前显示的检测组件步骤序号（控制v-show显示哪个组件）
const stepsActive = ref(-1) // 当前实际执行的业务步骤序号（控制业务逻辑分支）

// ====================== 状态管理变量 ======================
const ActiveStatue = ref('waiting') // 当前步骤的整体状态（waiting/start/process/success/error等）
const preTestStatus = ref('waiting') // 预检测执行状态
const timeTestStatus = ref('waiting') // 守时校验执行状态  
const channelsTestStatus = ref('waiting') // 通道系数校准执行状态
const TestStatus = ref('waiting') // 正式检测执行状态
const webMsgSend = ref() // webSocket推送的数据，用于组件间通信

// ====================== WebSocket 相关 ======================
const dataSocket = reactive({
  socketServe: socketClient.Instance, // WebSocket客户端实例
})

// ====================== 检测项选择状态 ======================
// 根据用户勾选的检测内容动态显示对应的检测步骤和组件
const preTestSelected = ref(false) // 是否选择预检测
const timeTestSelected = ref(false) // 是否选择守时检测
const channelsTestSelected = ref(false) // 是否选择系数校准
const testSelected = ref(false) // 是否选择正式检测

// ====================== 初始化操作 ======================
/**
 * 初始化操作 - 重置所有状态并根据用户选择的检测项设置初始步骤
 */
const initOperate = () => {
  // 重置所有状态为等待状态
  ActiveStatue.value = 'waiting'
  preTestStatus.value = 'waiting'
  timeTestStatus.value = 'waiting'
  channelsTestStatus.value = 'waiting'
  TestStatus.value = 'waiting'

  // 重置步骤和组件显示状态
  stepsActiveIndex.value = 1
  showComponent.value = true

  // 从store中获取用户勾选的检测内容
  preTestSelected.value = checkStore.selectTestItems.preTest
  timeTestSelected.value = checkStore.selectTestItems.timeTest
  channelsTestSelected.value = checkStore.selectTestItems.channelsTest
  testSelected.value = checkStore.selectTestItems.test

  // 计算总步骤数（选中的检测项 + 1个完成步骤）
  let count = 0
  for (let key in checkStore.selectTestItems) {
    if (checkStore.selectTestItems[key]) {
      count++
    }
  }
  stepsTotalNum.value = count + 1

  // 根据选中的检测项，设置初始显示的步骤（按优先级：预检测 > 守时检测 > 系数校准 > 正式检测）
  if (preTestSelected.value) {
    stepsActiveView.value = 1 // 显示预检测组件
    stepsActive.value = 1 // 业务逻辑设为预检测
    return
  }
  if (timeTestSelected.value) {
    stepsActiveView.value = 2 // 显示守时检测组件
    stepsActive.value = 2 // 业务逻辑设为守时检测
    return
  }
  if (channelsTestSelected.value) {
    stepsActiveView.value = 3 // 显示系数校准组件
    stepsActive.value = 3 // 业务逻辑设为系数校准
    return
  }
  if (testSelected.value) {
    stepsActiveView.value = 4 // 显示正式检测组件
    stepsActive.value = 4 // 业务逻辑设为正式检测
    return
  }
}

// ====================== 弹窗开启方法 ======================
/**
 * 打开检测弹窗
 * @param title 弹窗标题
 */
const open = (title: string) => {
  showSteps.value = true // 显示步骤条
  initOperate() // 初始化所有状态和步骤
  dialogTitle.value = title // 设置弹窗标题
  dialogVisible.value = true // 显示弹窗

  // 如果预检测组件存在，初始化其参数
  if (preTestRef.value) {
    preTestRef.value.initializeParameters()
  }

  // 创建WebSocket连接
  socketClient.Instance.connect()
  dataSocket.socketServe = socketClient.Instance

  // 注册WebSocket消息回调处理
  dataSocket.socketServe.registerCallBack('aaa', (res) => {
    // 将接收到的数据传递给子组件
    webMsgSend.value = res
  })
}

// ====================== 开始检测处理 ======================
/**
 * 快速开始检测 - 根据当前步骤执行对应的检测逻辑
 */
const handleSubmitFast = () => {
  // 获取设备ID列表和计划ID
  let deviceIds = checkStore.devices.map((item) => item.deviceId)
  let planId = checkStore.plan.id

  // 检查WebSocket连接状态
  if (!dataSocket.socketServe.connected) {
    ElMessage.error('webSocket连接中断！')
    return
  }

  console.log('handleSubmit', stepsActive.value, TestStatus.value)

  // 根据当前激活的步骤执行对应的检测逻辑
  switch (stepsActive.value) {
    case 1: // 预检测步骤
      if (preTestStatus.value == 'waiting') {
        if (checkStore.selectTestItems.preTest) {
          // 启动预检测
          startPreTest({
            userPageId: JwtUtil.getLoginName(),
            devIds: deviceIds,
            planId: planId,
            reCheckType: checkStore.reCheckType == 1 ? '1' : '2', // 操作类型：1为预检测，2为正式检测
            userId: userStore.userInfo.id,
            temperature: checkStore.temperature,
            humidity: checkStore.humidity,
            testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test],
          }).then(res => {
            if (res.code !== 'A0000') {
              ElMessageBox.alert('预检测失败', '检测失败', {
                confirmButtonText: '确定',
                type: 'error',
              })
              preTestStatus.value = 'error'
            }
          })
          preTestStatus.value = 'start'
        }
      }
      break
    case 2: // 守时检测步骤
      timeTestStatus.value = 'start'
      break
    case 3: // 系数校准步骤
      if (channelsTestStatus.value == 'waiting') {
        // 如果没有预检测且有系数校准，需要先进行初始化
        if (!checkStore.selectTestItems.preTest && checkStore.selectTestItems.channelsTest) {
          startPreTest({
            userPageId: JwtUtil.getLoginName(),
            devIds: deviceIds,
            planId: planId,
            reCheckType: checkStore.reCheckType == 1 ? '1' : '2',
            userId: userStore.userInfo.id,
            temperature: checkStore.temperature,
            humidity: checkStore.humidity,
            testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test],
          }).then(res => {
            if (res.code !== 'A0000') {
              ElMessageBox.alert('系数校准失败', '检测失败', {
                confirmButtonText: '确定',
                type: 'error',
              })
              channelsTestStatus.value = 'error'
            }
          })
        }
        channelsTestStatus.value = 'start'
      }
      break
    case 4: // 正式检测步骤
      if (TestStatus.value == 'waiting') {
        // 如果没有预检测和系数校准，直接进行正式检测需要先初始化
        if (!checkStore.selectTestItems.preTest && !checkStore.selectTestItems.channelsTest && checkStore.selectTestItems.test) {
          startPreTest({
            userPageId: JwtUtil.getLoginName(),
            devIds: deviceIds,
            planId: planId,
            reCheckType: checkStore.reCheckType == 1 ? '1' : '2',
            userId: userStore.userInfo.id,
            temperature: checkStore.temperature,
            humidity: checkStore.humidity,
            testItemList: [checkStore.selectTestItems.preTest, checkStore.selectTestItems.channelsTest, checkStore.selectTestItems.test],
          }).then(res => {
            if (res.code !== 'A0000') {
              ElMessageBox.alert('正式检测失败', '检测失败', {
                confirmButtonText: '确定',
                type: 'error',
              })
              TestStatus.value = 'error'
            }
          })
        }
        TestStatus.value = 'start'
      } else if (TestStatus.value == 'paused') {
        // 如果是暂停状态，发送继续指令
        sendResume()
      }
      break
    default:
      break
  }
}


// ====================== 事件定义 ======================
const emit = defineEmits<{
  (e: 'quitClicked'): void; // 退出检测事件
}>()

// ====================== 状态监听器 ======================
// 监听各个检测步骤的状态变化，并同步到总体状态
watch(preTestStatus, function(newValue, oldValue) {
  console.log('预检测状态变化：', newValue, oldValue)
  ActiveStatue.value = newValue // 同步到总体状态
})

watch(timeTestStatus, function(newValue, oldValue) {
  console.log('守时检测状态变化：', newValue, oldValue)
  ActiveStatue.value = newValue // 同步到总体状态
})

watch(channelsTestStatus, function(newValue, oldValue) {
  console.log('系数校准状态变化：', newValue, oldValue)
  ActiveStatue.value = newValue // 同步到总体状态
})

watch(TestStatus, function(newValue, oldValue) {
  console.log('正式检测状态变化：', newValue, oldValue)
  ActiveStatue.value = newValue // 同步到总体状态
})

// 监听总体状态变化，处理步骤切换和错误状态
watch(ActiveStatue, function(newValue, oldValue) {
  console.log('总体状态变化：', newValue, oldValue)

  // 处理错误状态
  if (newValue === 'error') {
    stepsActiveIndex.value = stepsTotalNum.value + 1 // 跳到最后一步
    nextStepText.value = '检测失败'
  }

  // 处理成功完成状态（已到达最后一个检测步骤）
  if (newValue === 'success' && stepsActiveIndex.value === stepsTotalNum.value - 1) {
    stepsActiveIndex.value += 2 // 跳到完成状态
    console.log('success')
    nextStepText.value = '检测完成'
  }

  // 处理连接超时状态
  if (newValue === 'connect_timeout') {
    stepsActiveIndex.value += 2 // 跳过当前步骤
    console.log('connect_timeout')
    nextStepText.value = '连接超时'
  }

  // 处理暂停超时状态
  if (newValue === 'pause_timeout') {
    stepsActiveIndex.value += 2 // 跳过当前步骤
    console.log('pause_timeout')
    nextStepText.value = '暂停超时'
  }

  // 处理成功状态的自动步骤切换（还有后续步骤时）
  if (newValue === 'success' && stepsActiveIndex.value < stepsTotalNum.value - 1) {
    nextStep() // 自动进入下一个测试步骤
    handleSubmitFast() // 自动开始下一步检测
  }
})

// ====================== 退出和暂停恢复处理 ======================
/**
 * 处理退出检测
 */
const handleQuit = () => {
  console.log('handleQuit', ActiveStatue.value)
  
  // 可以直接关闭的安全状态：未检测、检测完成、检测失败或异常情况
  const safeExitStates = [
    'waiting',           // 未开始检测
    'success',           // 检测完成
    'error',             // 检测失败
    'connect_timeout',   // 连接超时
    'pause_timeout'      // 暂停超时
  ]
  
  // 需要确认退出的状态：所有进行中、暂停中等状态
  const needConfirmStates = [
    'start',             // 开始检测
    'process',           // 检测进行中
    'test_init',         // 初始化中
    'paused',            // 已暂停（用户可能想要继续）
    'paused_ing'         // 暂停中
  ]
  
  if (safeExitStates.includes(ActiveStatue.value)) {
    handleClose() // 安全状态直接关闭
  } else {
    beforeClose() // 需要确认的状态
  }
}

/**
 * 处理暂停检测
 */
const handlePause = () => {
  sendPause() // 发送暂停指令
  testRef.value?.handlePause() // 调用正式检测组件的暂停方法
}

/**
 * 发送暂停指令
 */
const sendPause = () => {
  console.log('发起暂停请求')

  TestStatus.value = 'paused_ing' // 设置为暂停中状态
  pauseTest() // 调用暂停API
}

/**
 * 发送继续检测指令
 */
const sendResume = () => {
  console.log('发起继续检测请求')
  // 调用继续检测API
  resumeTest({
    userPageId: JwtUtil.getLoginName(),
    devIds: checkStore.devices.map((item) => item.deviceId),
    planId: checkStore.plan.id,
    reCheckType: '2', // 操作类型：0-系数校验，1-预检测，2-正式检测，8-不合格项复检
    userId: userStore.userInfo.id,
    temperature: checkStore.temperature,
    humidity: checkStore.humidity,
  })

  // 发送继续成功消息给子组件
  Object.assign(webMsgSend.value, {
    requestId: 'Resume_Success',
  })
}

/**
 * 关闭WebSocket连接
 */
const closeWebSocket = () => {
  // 检查连接状态，避免重复关闭WebSocket连接
  if (dataSocket.socketServe.connected) {
    dataSocket.socketServe.closeWs()
  }
}

// ====================== 步骤切换处理 ======================
/**
 * 进入下一步检测 - 复杂的步骤切换逻辑
 */
const nextStep = () => {
  // 如果已到最后或遇到错误状态，直接关闭弹窗
  if (stepsActiveIndex.value == stepsTotalNum.value + 1 || ActiveStatue.value === 'error' || ActiveStatue.value === 'connect_timeout' || ActiveStatue.value === 'pause_timeout') {
    handleClose()
    return
  }

  // 如果不是错误状态，进行步骤切换
  if (ActiveStatue.value != 'error') {
    ActiveStatue.value = 'waiting' // 重置为等待状态
    let tempStep = stepsActiveIndex.value
    let idx = 1
    stepsActiveIndex.value++ // 步骤索引递增

    // 遍历检测项，找到下一个需要执行的步骤
    for (let selectTestItemsKey in checkStore.selectTestItems) {
      if (tempStep == 0 && checkStore.selectTestItems[selectTestItemsKey]) {
        // 找到下一个要执行的检测项
        stepsActiveView.value = idx // 设置显示的组件
        stepsActive.value = idx // 设置业务逻辑步骤
        return
      }
      if (checkStore.selectTestItems[selectTestItemsKey] && tempStep != 0) {
        tempStep-- // 跳过已选择的检测项
      }
      idx++
    }
  }
}

/**
 * 处理步骤点击 - 允许点击回到之前已完成的步骤
 * @param step 点击的步骤序号
 */
const handleStepClick = (step: number) => {
  if (step > stepsActive.value) {
    return // 不能点击未完成的步骤
  } else {
    stepsActiveView.value = step // 切换到点击的步骤显示
  }
}

// ====================== 数据清理和关闭处理 ======================
/**
 * 清理所有数据状态
 */
function clearData() {
  stepsTotalNum.value = -1
  stepsActiveIndex.value = 1
  stepsActiveView.value = -1
  preTestStatus.value = 'waiting'
  timeTestStatus.value = 'waiting'
  channelsTestStatus.value = 'waiting'
  TestStatus.value = 'waiting'
  ActiveStatue.value = 'waiting'
  nextStepText.value = '下一步'
}

/**
 * 关闭前确认处理
 */
const beforeClose = () => {
  // 如果检测未完成且不是错误状态，需要用户确认
  if (stepsActiveIndex.value < stepsTotalNum.value && ActiveStatue.value != 'error') {
    ElMessageBox.confirm('检测未完成，是否退出当前检测流程?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      },
    ).then(() => {
      handleClose() // 用户确认后关闭
    })
  } else {
    handleClose() // 直接关闭
  }
}

/**
 * 关闭弹窗并清理资源
 */
const handleClose = () => {
  showSteps.value = false // 隐藏步骤条
  closeWebSocket() // 统一通过closeWebSocket函数关闭连接，避免重复关闭
  dialogVisible.value = false // 隐藏弹窗
  clearData() // 清理所有状态数据
  showComponent.value = false // 隐藏检测组件

  emit('quitClicked') // 触发退出事件通知父组件
}

// ====================== 生命周期处理 ======================
/**
 * 组件卸载前的清理工作
 * 确保路由切换或组件销毁时正确关闭WebSocket连接
 */
onBeforeUnmount(() => {
  closeWebSocket() // 组件销毁前关闭WebSocket连接
})

// ====================== 对外暴露的方法 ======================
defineExpose({ open }) // 只暴露open方法供父组件调用
</script>

<style scoped lang='scss'>

.test-head-steps {
  ::v-deep .el-step {
    .el-step__head.is-success {
      color: #91cc75;
    }

    .el-step__title.is-success {
      color: #91cc75;
    }
  }
}

:deep(.dialog-big .el-dialog__body) {
  max-height: 840px !important;
}

.steps-container :deep(.test-head-steps) {
  height: 80px;
  margin-bottom: 10px;
}

.steps-container :deep(.el-step__title) {
  font-size: 20px !important; /* 设置标题字体大小 */
  vertical-align: baseline !important;
  display: inline-block; /* 确保文字和图标在同一行 */
  line-height: 1; /* 调整行高以确保底部对齐 */
}

.steps-container :deep(.el-step__icon-inner) {
  font-size: 18px !important;
  vertical-align: baseline !important;
  display: inline-block; /* 确保文字和图标在同一行 */
  line-height: 1; /* 调整行高以确保底部对齐 */
}

.steps-container :deep(.el-step__icon) {
  font-size: 18px !important;
  vertical-align: baseline !important;
  display: inline-block; /* 确保文字和图标在同一行 */
  line-height: 1; /* 调整行高以确保底部对齐 */
}

.loading-box {
  animation: loading 1.5s linear infinite;
}

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


</style>