<template>
  <div>
    <el-tabs type="border-card">
      <el-tab-pane label="预检测项目">
        <div class="form-grid">
          <el-checkbox v-for="(item, index) in detectionOptions" v-model="item.selected" :key="index"
                       :label="item.name" disabled></el-checkbox>
        </div>
      </el-tab-pane>
    </el-tabs>

    <div class="test-dialog">
      <div class="dialog-left">
        <el-steps direction="vertical" :active="activeIndex" finish-status="success">
          <el-step :status="step1" title="源通讯校验"/>
          <el-step :status="step2" title="设备通讯校验"/>
          <el-step :status="step3" title="协议校验"/>
          <el-step :status="step4" title="相序校验"/>
          <el-step :status="step5" :title="ts === 'error'? '检测失败':ts === 'process'? '检测中':ts === 'success'? '检测成功':'待检测'"/>
        </el-steps>
      </div>
      <div class="dialog-right">
        <el-collapse v-model="collapseActiveName" accordion>
          <el-collapse-item title="源通讯校验" name="1">
            <div class="div-log">
              <p v-for="(item, index) in step1InitLog" :key="index"
                 :style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
                {{ item.log }} <br/>
              </p>
            </div>
          </el-collapse-item>
          <el-collapse-item title="设备通讯校验" name="2">
            <div class="div-log">
              <p v-for="(item, index) in step2InitLog" :key="index"
                 :style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
                {{ item.log }} <br/>
              </p>
            </div>
          </el-collapse-item>
          <el-collapse-item title="协议校验" name="3">
            <div class="div-log">
              <p v-for="(item, index) in step3InitLog" :key="index"
                 :style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
                {{ item.log }} <br/>
              </p>
            </div>
          </el-collapse-item>
          <el-collapse-item title="相序校验" name="4">
            <div class="div-log">
              <p v-for="(item, index) in step4InitLog" :key="index"
                 :style="{ color: item.type === 'error' ? '#F56C6C' : 'var(--el-text-color-regular)' }">
                {{ item.log.split('&&')[0] }}
                <br v-if="item.log.includes('&&')"/>
                &nbsp;&nbsp;&nbsp;&nbsp;{{ item.log.split('&&')[1] }}

                <br v-if="item.log.includes('&&')"/>
                &nbsp;&nbsp;&nbsp;&nbsp;{{ item.log.split('&&')[2] }}

              </p>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>
    </div>
  </div>

</template>
<script lang="tsx" setup name="preTest">
/**
 * 预检测组件
 * 负责电力设备检测中的预检测阶段，包含4个步骤：
 * 1. 源通讯校验 - 验证源端通讯是否正常
 * 2. 设备通讯校验 - 检查设备IP、端口、识别码、密钥
 * 3. 协议校验 - 进行ICD报告触发测试
 * 4. 相序校验 - 判断装置接线是否正确
 */
import {ElMessage, ElMessageBox} from "element-plus";
import {defineExpose, ref, toRef, watch} from 'vue';

// ==================== 日志数据存储 ====================
// 各步骤的日志数据，用于在右侧折叠面板中显示实时日志
const step1InitLog = ref([
  {
    type: 'info',
    log: '暂无数据，等待检测开始',
  },
])

const step2InitLog = ref([
  {
    type: 'info',
    log: '暂无数据，等待检测开始',
  },
])

const step3InitLog = ref([
  {
    type: 'info',
    log: '暂无数据，等待检测开始',
  },
])

const step4InitLog = ref([
  {
    type: 'info',
    log: '暂无数据，等待检测开始',
  },
])

// ==================== 界面状态控制 ====================
const collapseActiveName = ref('1') // 当前展开的折叠面板
const activeIndex = ref(0) // 当前激活的步骤索引（用于步骤条高亮）
const activeTotalNum = ref(5) // 总步骤数

// ==================== 步骤状态管理 ====================
// 各步骤的执行状态：wait/process/success/error
const step1 = ref('wait') // 源通讯校验状态
const step2 = ref('wait') // 设备通讯校验状态
const step3 = ref('wait') // 协议校验状态
const step4 = ref('wait') // 相序校验状态
const step5 = ref('wait') // 整体检测结果状态

// ==================== 预检测项目配置 ====================
// 定义预检测包含的检测项目（顶部tabs显示用，只读）
const detectionOptions = ref([
  {
    id: 0,
    name: "源通讯检测",//判断源通讯是否正常
    selected: true,
  },
  {
    id: 1,
    name: "设备通讯检测",//判断设备的IP、Port、识别码、秘钥是否正常
    selected: true,
  },
  {
    id: 2,
    name: "协议校验",//ICD报告触发测试
    selected: true,
  },
  {
    id: 3,
    name: "相序校验",//判断装置的接线是否正确
    selected: true,
  }
]);


// ==================== 组件Props定义 ====================
const props = defineProps({
  testStatus: {
    type: String,
    default: 'wait' // 从父组件接收的测试状态
  },
  webMsgSend: {
    type: Object,
    default: () => ({}) // 从父组件接收的WebSocket消息
  }
})

// ==================== 响应式Props引用 ====================
const testStatus = toRef(props, 'testStatus');
const webMsgSend = toRef(props, 'webMsgSend');
const ts = ref(''); // 内部测试状态，用于向父组件同步

// ==================== 错误处理函数 ====================
/**
 * 处理致命错误 - 会终止整个检测流程
 * @param stepRef 当前步骤状态引用
 * @param logRef 当前步骤日志引用  
 * @param message 错误消息
 */
function handleFatalError(stepRef: any, logRef: any, message: string) {
  stepRef.value = 'error';
  ts.value = 'error';
  step5.value = 'error';
  logRef.value = [{
    type: 'error',
    log: message
  }];
}

/**
 * 处理警告错误 - 只标记当前步骤失败，检测可继续
 * @param stepRef 当前步骤状态引用
 * @param logRef 当前步骤日志引用
 * @param message 错误消息
 */
function handleWarningError(stepRef: any, logRef: any, message: string) {
  stepRef.value = 'error';
  logRef.value.push({
    type: 'error',
    log: message
  });
}

// ==================== WebSocket消息处理 ====================
/**
 * 监听WebSocket消息，根据不同的requestId和operateCode处理各种检测状态
 * 主要消息类型：
 * - yjc_ytxjy: 源通讯校验
 * - yjc_sbtxjy: 设备通讯校验  
 * - yjc_xyjy: 协议校验
 * - YJC_xujy: 相序校验
 */
watch(webMsgSend, function (newValue, oldValue) {
  if (testStatus.value !== 'waiting') {
    switch (newValue.requestId) {
      case 'yjc_ytxjy':
        switch (newValue.operateCode) {
          case 'INIT_GATHER':
            if (newValue.code == 10200) {
              step1InitLog.value.push({
                type: 'info',
                log: '源初始化成功!',
              })
              activeIndex.value = 1
              step1.value = 'success'
              step2.value = 'process'
            } else if (newValue.code == 10201) {
              step1.value = 'process'
              step1InitLog.value = [{
                type: 'wait',
                log: '正在进行源初始化!',
              }];
            } else if (newValue.code == 10552) {
              ElMessage.error(newValue.code)
              handleFatalError(step1, step1InitLog, '重复的初始化操作!')
            } else if (newValue.code == 10523) {
              handleFatalError(step1, step1InitLog, '源连接失败!')
            } else if (newValue.code == -1) {
              handleFatalError(step1, step1InitLog, '源未知异常!')
            }
            break;
        }
        break;
      case 'yjc_sbtxjy':
        switch (newValue.operateCode) {
          case 'INIT_GATHER$01':
            if (newValue.code == 10200) {
              step2InitLog.value.push({
                type: 'info',
                log: newValue.data + '设备通讯校验成功!',
              })

            } else if (newValue.code == 10201) {
              step2.value = 'process'
              step2InitLog.value = [{
                type: 'wait',
                log: '正在进行设备通讯校验.....',
              }];
            } else if (newValue.code == 10550) {
              handleWarningError(step2, step2InitLog, newValue.data + '设备连接异常!')
            } else if (newValue.code == 10551) {
              handleFatalError(step2, step2InitLog, newValue.data + '设备触发报告异常!')
            } else if (newValue.code == 10552) {
              handleFatalError(step2, step2InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测！')
            } else if (newValue.code == 25001) {
              activeIndex.value = 2
              step2.value = 'success'
              step3.value = 'process'
            }
            break;
        }
        break;
      case 'yjc_xyjy':
        switch (newValue.operateCode) {
          case 'INIT_GATHER$01':
            if (newValue.code == 10200) {
              step3InitLog.value.push({
                type: 'info',
                log: '统计数据协议校验:' + newValue.data + '通讯协议校验成功!',
              })

            } else if (newValue.code == 10201) {
              step3.value = 'process'
              step3InitLog.value = [{
                type: 'wait',
                log: '正在进行通讯协议校验.....',
              }];
            } else if (newValue.code == 10550) {
              handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
            } else if (newValue.code == 10551) {
              handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
            } else if (newValue.code == 10552) {
              handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测！')
            }
            break;
          case 'INIT_GATHER$02':
            if (newValue.code == 10200) {
              step3InitLog.value.push({
                type: 'info',
                log: '实时数据协议校验:' + newValue.data + '通讯协议校验成功!',
              })

            } else if (newValue.code == 10201) {
              step3.value = 'process'
              step3InitLog.value = [{
                type: 'wait',
                log: '正在进行通讯协议校验.....',
              }];
            } else if (newValue.code == 10550) {
              handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
            } else if (newValue.code == 10551) {
              handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
            } else if (newValue.code == 10552) {
              handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测！')
            }
            break;
          case 'INIT_GATHER$03':
            if (newValue.code == 10200) {
              step3InitLog.value.push({
                type: 'info',
                log: '暂态数据协议校验:' + newValue.data + '通讯协议校验成功!',
              })

            } else if (newValue.code == 10201) {
              step3.value = 'process'
            } else if (newValue.code == 10550) {
              handleWarningError(step3, step3InitLog, newValue.data + '设备连接异常!')
            } else if (newValue.code == 10551) {
              handleFatalError(step3, step3InitLog, newValue.data + '设备触发报告异常!')
            } else if (newValue.code == 10552) {
              handleFatalError(step3, step3InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测！')
            }
            break;
          case 'VERIFY_MAPPING$01':
            if (newValue.code == 25001) {
              activeIndex.value = 3
              step3.value = 'success'
              step4.value = 'process'
            } else if (newValue.code == 10200) {
              let data = JSON.parse(newValue.data)
              handleFatalError(step3, step3InitLog, `脚本与icd检验失败! icd名称：${data['icdType']} -> 校验项：${data['dataType']}`)
            } else if (newValue.code == 10500) {
              handleFatalError(step3, step3InitLog, '装置中未找到该icd！')
            }
            break;
        }
        break;
      case 'YJC_xujy':
        switch (newValue.operateCode) {
          case 'OPER_GATHER':
            if (newValue.code == 10200) {
              step4InitLog.value.push({
                type: 'info',
                log: '源参数下发成功,等待校验中.....',
              })

            } else if (newValue.code == 10201) {
              step4.value = 'process'
              step4InitLog.value = [{
                type: 'wait',
                log: '源参数下发中.....',
              }];
            } else if (newValue.code == 10552) {
              ElMessage.error("存在已经初始化步骤,已经自动关闭,请重新发起检测！")
              handleFatalError(step4, step4InitLog, '存在已经初始化步骤,执行自动关闭,请重新发起检测！')
            } else if (newValue.code == 10520) {
              handleFatalError(step4, step4InitLog, '解析报文异常')
            }
            break;
          case 'DATA_REQUEST$02':
            if (newValue.code == 10200) {
              let type = 'info'
              if (newValue.data.includes('不合格')) {
                type = 'error'
              }
              newValue.data.split('<br/>')
              step4InitLog.value.push({
                type: type,
                log: newValue.data,
              })
            } else if (newValue.code == 10201) {
              step4.value = 'process'
              step4InitLog.value = [{
                type: 'wait',
                log: '获取数据相序校验数据!',
              }];
            } else if (newValue.code == 25003) {
              handleFatalError(step4, step4InitLog, '相序校验未通过!')
            } else if (newValue.code == 25001) {
              step4.value = 'success'
              step5.value = 'success'
              step4InitLog.value.push({
                type: 'wait',
                log: '相序校验成功!',
              })
              ts.value = 'success'
            }
            activeIndex.value = 5
            console.log("@@@@", ts.value)
            break
        }
        break;
      case 'quit':
        break;
      case 'connect':
        switch (newValue.operateCode) {
          case "Source":
            handleFatalError(step1, step1InitLog, '源服务端连接失败!')
            break;
          case "Dev":
            handleFatalError(step2, step2InitLog, '设备服务端连接失败!')
            break;
        }
        break;
      case 'unknown_operate':
        break;
      case 'error_flow_end':
        ElMessageBox.alert(`当前流程存在异常结束！`, '检测失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        // 根据当前步骤选择对应的日志记录
        const currentStepLog = activeIndex.value === 0 ? step1InitLog :
                              activeIndex.value === 1 ? step2InitLog :
                              activeIndex.value === 2 ? step3InitLog : step4InitLog
        const currentStep = activeIndex.value === 0 ? step1 :
                           activeIndex.value === 1 ? step2 :
                           activeIndex.value === 2 ? step3 : step4
        handleFatalError(currentStep, currentStepLog, '设备连接异常，检测终止！')
        break;
      case 'socket_timeout':
        ElMessageBox.alert(`设备连接异常，请检查设备连接情况！`, '检测失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        // 根据当前步骤选择对应的日志记录
        const timeoutStepLog = activeIndex.value === 0 ? step1InitLog :
                              activeIndex.value === 1 ? step2InitLog :
                              activeIndex.value === 2 ? step3InitLog : step4InitLog
        const timeoutStep = activeIndex.value === 0 ? step1 :
                           activeIndex.value === 1 ? step2 :
                           activeIndex.value === 2 ? step3 : step4
        handleFatalError(timeoutStep, timeoutStepLog, 'Socket连接超时，检测终止！')
        break;
      case 'server_error':
        ElMessageBox.alert('服务端主动关闭连接!', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        // 根据当前步骤选择对应的日志记录
        const serverStepLog = activeIndex.value === 0 ? step1InitLog :
                             activeIndex.value === 1 ? step2InitLog :
                             activeIndex.value === 2 ? step3InitLog : step4InitLog
        const serverStep = activeIndex.value === 0 ? step1 :
                          activeIndex.value === 1 ? step2 :
                          activeIndex.value === 2 ? step3 : step4
        handleFatalError(serverStep, serverStepLog, '服务端主动关闭连接！')
        break;
      case 'device_error':
        ElMessageBox.alert('设备主动关闭连接!', '初始化失败', {
          confirmButtonText: '确定',
          type: 'error',
        })
        // 根据当前步骤选择对应的日志记录
        const deviceStepLog = activeIndex.value === 0 ? step1InitLog :
                             activeIndex.value === 1 ? step2InitLog :
                             activeIndex.value === 2 ? step3InitLog : step4InitLog
        const deviceStep = activeIndex.value === 0 ? step1 :
                          activeIndex.value === 1 ? step2 :
                          activeIndex.value === 2 ? step3 : step4
        handleFatalError(deviceStep, deviceStepLog, '设备主动关闭连接！')
        break;
    }
  }
})

// ==================== 界面联动控制 ====================
/**
 * 监听当前激活步骤，自动展开对应的日志折叠面板
 */
watch(activeIndex, function (newValue, oldValue) {
  if (newValue <= activeTotalNum.value - 2) {
    collapseActiveName.value = (newValue + 1).toString()
  } else {
    collapseActiveName.value = (newValue - 1).toString()
  }
})

/**
 * 监听父组件传入的测试状态变化
 * 处理测试开始和重置逻辑
 */
watch(testStatus, function (newValue, oldValue) {
  ts.value = props.testStatus;
  if (ts.value === 'start') {
    ts.value = 'process'
  } else if (ts.value === 'waiting') {
    activeIndex.value = 0
    step1InitLog.value = [
      {
        type: 'info',
        log: '暂无数据，等待检测开始',
      },
    ]
    step1.value = 'finish'
    step2.value = 'wait'
    step3.value = 'wait'
    step4.value = 'wait'
    step5.value = 'wait'
  }
})

// ==================== 父子组件通信 ====================
const emit = defineEmits(['update:testStatus']);

/**
 * 监听内部测试状态变化，同步给父组件
 * 实现双向数据绑定
 */
watch(ts, function (newValue, oldValue) {
  emit('update:testStatus', ts.value)
})


// ==================== 对外暴露方法 ====================
/**
 * 初始化参数方法
 * 由父组件调用，用于重置所有步骤状态和日志
 */
function initializeParameters() {
  activeIndex.value = 0
  step1.value = 'process'
  step2.value = 'wait'
  step3.value = 'wait'
  step4.value = 'wait'
  step5.value = 'wait'

  step1InitLog.value = [
    {
      type: 'info',
      log: '暂无数据，等待检测开始',
    },
  ]
  step2InitLog.value = [
    {
      type: 'info',
      log: '暂无数据，等待检测开始',
    },
  ]
  step3InitLog.value = [
    {
      type: 'info',
      log: '暂无数据，等待检测开始',
    },
  ]
  step4InitLog.value = [
    {
      type: 'info',
      log: '暂无数据，等待检测开始',
    },
  ]

}


// 暴露方法给父组件使用
defineExpose({
  initializeParameters,
});
</script>
<style scoped lang="scss">
.test-dialog {
  height: 350px;
  display: flex;

  flex-direction: row;
  /* 横向排列 */
  margin-top: 20px;
}

.dialog-left {
  width: 15%;
  margin-left: 20px;
}


.dialog-right {
  margin-left: 20px;
  width: 80%;
  height: 100%;
}

.dialog-right :deep(.el-collapse-item__header) {
  font-size: 16px;
}

.div-log {
  height: 145px;
  overflow-y: auto;
  padding-left: 10px;

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

}
</style>
