﻿<template>
  <el-dialog
    :model-value="dialogVisible"
    :title="dialogTitle"
    :width="dialogWidth"
    :style="dialogStyle"
    :close-on-click-modal="dialogBig.closeOnClickModal"
    :draggable="dialogBig.draggable"
    :class="dialogBig.class"
    :show-close="true"
    :close-on-press-escape="false"
    :before-close="handleBeforeClose"
    destroy-on-close
    align-center
  >
    <div class="freq-converter-test-popup">
      <el-steps :active="currentStep - 1" finish-status="success" simple>
        <el-step title="准备" />
        <el-step title="检测" />
      </el-steps>

      <FreqConverterDetectChannelPairing
        v-if="dialogVisible && currentStep === 1"
        ref="channelPairingRef"
        :freq-converter="currentFreqConverter"
      />

      <FreqConverterDipChart
        v-else-if="dialogVisible && currentStep === 2"
        :selected-mapping="selectedMapping"
        :web-msg-send="webSocketMessage"
        :result-data="historyResultData"
        :auto-draw-curve="false"
      />
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button
          v-if="!startDetectSuccess"
          type="primary"
          :disabled="currentStep !== 1 || startLoading"
          :loading="startLoading"
          @click="handleStart"
        >
          开始检测
        </el-button>
        <el-button type="danger" plain @click="handleExit">退出检测</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import {ElMessage, ElMessageBox} from 'element-plus'
import {computed, onBeforeUnmount, onMounted, ref} from 'vue'
import {dialogBig} from '@/utils/elementBind'
import {type FreqConverter} from '@/api/device/interface/freqConverter'
import {getFreqConverterResult, startFreqConverterDetect, stopFreqConverterDetect} from '@/api/device/freqConverter'
import {JwtUtil} from '@/utils/jwtUtil'
import FreqConverterDetectChannelPairing from '@/views/machine/freqConverter/components/freqConverterDetectChannelPairing.vue'
import FreqConverterDipChart from '@/views/machine/freqConverter/components/freqConverterDipChart.vue'
import socketClient from '@/utils/webSocketClient'

const SOCKET_CALLBACK_KEY = 'aaa'

const props = defineProps<{
  refreshTable?: (() => Promise<void>) | (() => void) | undefined;
}>()

const dialogVisible = ref(false)
const currentStep = ref(1)
const currentFreqConverter = ref<FreqConverter.ResFreqConverter | null>(null)
const channelPairingRef = ref<InstanceType<typeof FreqConverterDetectChannelPairing>>()
const webSocketMessage = ref<any>(null)
const historyResultData = ref<any>(null)
const socketServe = ref<typeof socketClient.Instance | null>(null)
const selectedMapping = ref<Record<string, any> | null>(null)
const startLoading = ref(false)
const startDetectSuccess = ref(false)
const hasSocketError = ref(false)
const viewportWidth = ref(typeof window === 'undefined' ? 1280 : window.innerWidth)

const dialogTitle = computed(() => '变频器检测')
const dialogWidth = computed(() => (viewportWidth.value < 820 ? 'calc(100vw - 24px)' : dialogBig.width))
const dialogStyle = computed(() => ({
  maxWidth: dialogBig.maxWidth,
  minWidth: viewportWidth.value < 820 ? '320px' : dialogBig.minWidth
}))

const SOCKET_ERROR_MESSAGE_MAP: Record<number, string> = {
  10550: '设备连接异常',
  10551: '设备触发报告异常',
  10552: '重复的初始化操作',
  10553: '通讯模块通讯异常',
  10554: '报文解析异常',
  10556: '不存在上线的设备',

  400:'请求格式或者参数错误',
  404:'未知错误',
  // 408:'超时',
  // 409:'业务执行不符合预期',
  500:'未知错误'
}

const normalizeFormalRealPayload = (payload: any) => {
  if (!payload || typeof payload !== 'object') {
    return payload
  }

  if (typeof payload.data !== 'string') {
    return payload
  }

  try {
    return {
      ...payload,
      data: JSON.parse(payload.data)
    }
  } catch (error) {
    console.error('formal_real 数据解析失败:', error, payload.data)
    return payload
  }
}

const extractResultArray = (payload: any) => {
  if (Array.isArray(payload)) {
    return payload
  }

  if (Array.isArray(payload?.data)) {
    return payload.data
  }

  if (Array.isArray(payload?.data?.records)) {
    return payload.data.records
  }

  if (Array.isArray(payload?.records)) {
    return payload.records
  }

  if (Array.isArray(payload?.list)) {
    return payload.list
  }

  return [] as any[]
}

const handleSocketMessage = (payload: any) => {
  const requestId = `${payload?.requestId ?? ''}`
  const normalizedRequestId = requestId.trim().toLowerCase()
  const code = Number(payload?.code)

  if (requestId === 'yjc_sbtxjy' && code !== 10200 || code in SOCKET_ERROR_MESSAGE_MAP) {
    hasSocketError.value = true
    ElMessage.error(SOCKET_ERROR_MESSAGE_MAP[code] || `检测异常，错误码：${code}`)
    return
  }

  if (normalizedRequestId.startsWith('formal_real')) {
    webSocketMessage.value = normalizeFormalRealPayload(payload)
  }
}

const updateViewportWidth = () => {
  viewportWidth.value = window.innerWidth
}

const connectWebSocket = () => {
  try {
    if (socketServe.value) {
      socketServe.value.unRegisterCallBack?.(SOCKET_CALLBACK_KEY)
      if (socketServe.value.connected) {
        socketServe.value.closeWs()
      }
    }

    socketClient.Instance.connect()
    socketServe.value = socketClient.Instance
    socketServe.value.registerCallBack(SOCKET_CALLBACK_KEY, handleSocketMessage)
  } catch (error) {
    console.error('WebSocket连接处理失败:', error)
    ElMessage.error('WebSocket连接建立失败，请重试')
  }
}

const closeWebSocket = () => {
  try {
    if (socketServe.value) {
      socketServe.value.unRegisterCallBack?.(SOCKET_CALLBACK_KEY)
      if (socketServe.value.connected) {
        socketServe.value.closeWs()
      }
      socketServe.value = null
    }
  } catch (error) {
    console.error('WebSocket关闭失败:', error)
    socketServe.value = null
  }
}

const resetState = () => {
  currentStep.value = 1
  webSocketMessage.value = null
  historyResultData.value = null
  currentFreqConverter.value = null
  selectedMapping.value = null
  startLoading.value = false
  startDetectSuccess.value = false
  hasSocketError.value = false
}

const closeDialog = () => {
  dialogVisible.value = false
  closeWebSocket()
  resetState()
}

const stopDetect = async () => {
  if (!startDetectSuccess.value) {
    return
  }

  try {
    await stopFreqConverterDetect({
      userId: JwtUtil.getLoginName()
    })
  } catch (error) {
    console.error('停止变频器检测失败:', error)
  }
}

const confirmExit = async () => {
  await ElMessageBox.confirm(
    '检测未完成，是否退出当前检测流程？',
    '提示',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  )
}

const isFreqConverterDetected = () => {
  return Number(currentFreqConverter.value?.testStatus) === 1
}

const confirmResetLastDetectData = async () => {
  if (!isFreqConverterDetected()) {
    return true
  }

  try {
    await ElMessageBox.confirm(
      '是否覆盖上次检测数据',
      '提示',
      {
        confirmButtonText: '是',
        cancelButtonText: '否',
        distinguishCancelAndClose: true,
        type: 'warning'
      }
    )
    return true
  } catch (action) {
    if (action === 'cancel') {
      return false
    }

    return null
  }
}

const handleBeforeClose = async (done: () => void) => {
  if (hasSocketError.value) {
    await stopDetect()
    closeDialog()
    await props.refreshTable?.()
    done()
    return
  }

  try {
    await confirmExit()
    await stopDetect()
    closeDialog()
    await props.refreshTable?.()
    done()
  } catch {
    // 用户取消关闭
  }
}

const handleStart = async () => {
  if (currentStep.value === 1) {
    const mapping = channelPairingRef.value?.getChannelMapping()
    if (!mapping || !channelPairingRef.value?.hasValidConnection()) {
      ElMessage.warning('请先选择设备通道并完成连线')
      return
    }

    const reset = await confirmResetLastDetectData()
    if (reset === null) {
      return
    }

    startLoading.value = true

    try {
      if (reset === false) {
        const historyResult = await getFreqConverterResult({
          converterId: mapping.freqConverterId
        })
        historyResultData.value = extractResultArray(historyResult?.data ?? historyResult)
      } else {
        historyResultData.value = null
      }

      const res = await startFreqConverterDetect({
        converterId: mapping.freqConverterId,
        monitorId: `${mapping.deviceId}_${mapping.deviceChannel}`,
        userId: JwtUtil.getLoginName(),
        reset
      })

      if (res.code === 'A0000') {
        selectedMapping.value = mapping
        currentStep.value = 2
        startDetectSuccess.value = true
        return
      }
    } catch (error) {
      console.error('开始变频器检测失败:', error)
      ElMessage.error('开始检测失败')
    } finally {
      startLoading.value = false
    }

    return
  }
}

const handleExit = async () => {
  if (!hasSocketError.value) {
    try {
      await confirmExit()
    } catch {
      return
    }
  }

  await stopDetect()
  closeDialog()
  await props.refreshTable?.()
}

const open = (row: FreqConverter.ResFreqConverter) => {
  resetState()
  currentFreqConverter.value = {...row}
  dialogVisible.value = true
  connectWebSocket()
}

onMounted(() => {
  window.addEventListener('resize', updateViewportWidth)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', updateViewportWidth)
  closeWebSocket()
})

defineExpose({open, channelPairingRef})
</script>

<style scoped>
.freq-converter-test-popup {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.section-card {
  border: 1px solid var(--el-border-color-light);
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.section-tip {
  color: var(--el-text-color-secondary);
  font-size: 12px;
}

:deep(.el-dialog__body) {
  padding-top: 10px;
  padding-bottom: 10px;
  overflow: hidden;
}
</style>
