<template>
  <div id="regular-container">
    <!-- 加载蒙层 -->
    <div class="loading-overlay" v-if="isLoading">
      <div class="loading-content">
        <div class="loading-spinner"></div>
        <span class="loading-text">正在扫描耗材...</span>
      </div>
    </div>
    <!-- 扫描结果弹窗 -->
    <div v-if="showScanResults" class="scan-results-overlay">
      <div class="scan-results-container">
        <div class="scan-results-header">
          <span class="title">扫描结果</span>
        </div>
        <div class="scan-results-content">
          <table class="scan-results-table">
            <thead>
              <tr>
                <th>通道</th>
                <th>项目名称</th>
                <th>批次号</th>
                <th>状态</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="report in formattedReports"
                :key="report.channel"
                :class="{ 'error-row': report.isError }"
              >
                <td>通道{{ report.channel + 1 }}</td>
                <td>{{ report.projName || '--' }}</td>
                <td>{{ report.lotId || '--' }}</td>
                <td :class="report.isError ? 'error-text' : 'success-text'">
                  {{ report.message }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>
        <div class="scan-results-footer">
          <button class="confirm-btn" @click="handleConfirmScan">确认</button>
        </div>
      </div>
    </div>

    <!--耗材页面 -->
    <div class="main-top">
      <div class="plate-area">
        <SpttingPlates :plates="plates" :temperature="currentTemperature" />

        <!-- <SliderAreaEx v-model="sliderValue" v-model:totalValue="totalVal"/>
        <DragAreaEx v-model:hVal="hVal" v-model:hTotal="hTotal" v-model:vVal="vVal" v-model:vTotal="vTotal"/> -->
      </div>
      <div class="move-liquid-area">
        <MoveLiquidArea
          :isLoad="isLoad"
          :isLoading="isLoading"
          :moveLiquids="moveLiquids"
          :tempTipNum="tempTipNum"
          :bufferBig="bufferBig"
          :emergencyInfo="emergencyInfo"
          :wasteStatus="wasteStatus"
          @loadConsumables="handleIsLoad"
          @unloadConsumables="handleIsUnload"
          @updateTipNum="updateTipNum"
        />
      </div>
    </div>
    <div class="main-bottom">
      <!--缓冲液区域小-->
      <div class="buffer-little-title">
        <div class="line"></div>
        <div class="content">缓冲液(小)</div>
      </div>
      <div class="ball-area">
        <MainComponent
          v-for="item in bufferLittles"
          :key="item"
          class="ball-grid"
          :projectName="item.projShortName"
          :currentCount="item.num"
          :totalBalls="25"
          :activatedBalls="item.num"
          :columns="5"
          gridWidth="240px"
          gridHeight="235px"
          :activeColor="item.color"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { MoveLiquidArea, SpttingPlates, MainComponent } from '../components'
import SliderAreaEx  from '../components/Consumables/SliderAreaEx.vue';
import DragAreaEx  from '../components/Consumables/DragAreaEx.vue';
import { ref, onMounted, onActivated, onBeforeUnmount, watch } from 'vue'
import {
  getInitState,
  scanConsumables,
  updateTipsNum,
} from '../../../services/Index/index'
import { useConsumablesStore, useEmergencyStore } from '../../../store'
import { useDeviceStore } from '../../../store/index'
import { eventBus } from '../../../eventBus'
import { ReactionPlate, BottleGroup, LiquidState } from '../../../types/Index'
import { createWebSocket } from '../../../websocket/socket'
import type {
  ConsumablesStateMessage,
  SensorStateMessage,
  EmergencyPosStateMessage,
} from '../../../websocket/socket'
import { getServerInfo } from '../../../utils/getServerInfo'
import { formatScanReports } from '../../../utils/errorHandler'
import { ElMessage } from 'element-plus'
const { wsUrl } = getServerInfo('/api/v1/app/ws/state')
const socket = createWebSocket(wsUrl)

const sliderValue = ref(25); // 初始值
const totalVal = ref(50)

const hVal = ref(10)
const hTotal = ref(60)
const vVal = ref(10)
const vTotal = ref(60)

const consumableStore = useConsumablesStore()
const emergencyStore = useEmergencyStore()
const deviceStore = useDeviceStore()
// 温度状态
const currentTemperature = ref(40)
// 废料区状态
const wasteStatus = ref(false)
// 父组件状态
const isLoad = ref(false)
const isLoading = ref(false)
// 反应板夹的状态
const plates = ref<ReactionPlate[]>([])
// 移液盘的状态
const moveLiquids = ref<LiquidState[]>([
  {
    id: 1,
    tipNum: 0,
  },
  {
    id: 2,
    tipNum: 0,
  },
  {
    id: 3,
    tipNum: 0,
  },
])
// 新增状态
const showScanResults = ref(false)
interface ScanReport {
  channel: number
  code: string
  message: string
  isError: boolean
  projName: string | null
  lotId: string | null
}
const formattedReports = ref<ScanReport[]>([])
//是否加载
const isAlreadyLoad = ref(false)
// 临时状态管理小球激活数量
const tempTipNum = ref<number[]>([
  ...moveLiquids.value.map((liquid) => liquid.tipNum),
])
//管理缓冲液小的状态
interface BufferLittle {
  id: number
  num: number
  projShortName: string
  color: string
  lotId?: string
  type?: string
  projId?: number
  projName?: string
}
const bufferLittles = ref<BufferLittle[]>([
  {
    id: 1,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
  {
    id: 2,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
  {
    id: 3,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
  {
    id: 4,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
  {
    id: 5,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
  {
    id: 6,
    num: 0,
    projShortName: '',
    color: '#4caf50',
  },
])
//管理大缓冲液的状态
const bufferBig = ref<BottleGroup[]>([])
//急诊区状态
const emergencyInfo = ref(emergencyStore.$state.emergencyInfo || {})
//是否处理扫描结果
const isHandleScan = ref(false)
// 确认扫描结果
const handleConfirmScan = () => {
  showScanResults.value = false
  isHandleScan.value = true
  if (formattedReports.value.some((report) => report.isError)) {
    isLoad.value = false
    isAlreadyLoad.value = false
    ElMessage.warning('存在错误，请检查耗材')
  }
}
//使用websocket保证数据的实时性
const startWebSocket = () => {
  socket.connect()
}
// 处理传感器状态消息
const handleSensorState = (data: SensorStateMessage['data']) => {
  // 更新温度值（这里使用孵育盒温度）
  currentTemperature.value = data.incubateBoxTemperature
  wasteStatus.value = data.wasteBinFullFlag
  consumableStore.updateWasteStatus(wasteStatus.value)
  // 可以添加温度异常处理逻辑
  if (currentTemperature.value > 40) {
    console.warn('温度过高警告')
    // 可以在这里添加其他警告逻辑
  }
}

//处理耗材状态
const handleConsumablesState = (data: ConsumablesStateMessage['data']) => {
  if (isAlreadyLoad.value && isHandleScan.value) {
    consumableStore.setConsumablesData(data)
    moveLiquids.value = data.tips
    plates.value = data.reactionPlateGroup as ReactionPlate[]
    bufferLittles.value = data.littBottleGroup as BufferLittle[]
    bufferBig.value = data.larBottleGroup as BottleGroup[]
  } else {
    return
  }
}
// 使用事件总线更新状态
const updatePlatesAndBuffers = ({
  value,
  index,
}: {
  value: number
  index: number
}) => {
  if (plates.value && plates.value[index]) {
    plates.value[index].num = value
  }
  if (bufferLittles.value && bufferLittles.value[index]) {
    bufferLittles.value[index].num = value
  }
  if (bufferBig.value && bufferBig.value[index]) {
    bufferBig.value[index].isUse = value > 0
  }
}
onMounted(() => {
  eventBus.on('confirm', updatePlatesAndBuffers)
  startWebSocket()
  socket.subscribe<SensorStateMessage>('SensorState', handleSensorState)
  socket.subscribe<ConsumablesStateMessage>(
    'ConsumablesStateService',
    handleConsumablesState,
  )
  // getEmergencyInfo()
})
onBeforeUnmount(() => {
  // 清除事件总线的监听
  eventBus.off('confirm', updatePlatesAndBuffers)
  if (socket !== null) {
    socket.disconnect() // 断开连接
  }
  socket.unsubscribe<SensorStateMessage>('SensorState', handleSensorState)
  socket.unsubscribe<ConsumablesStateMessage>(
    'ConsumablesStateService',
    handleConsumablesState,
  )
})
// 在组件激活时恢复状态
onActivated(() => {
  emergencyInfo.value = emergencyStore.$state.emergencyInfo || {}
  if (!isLoad.value) {
    console.log('组件被激活了')
  }
})
// 子组件传值
//存储耗材数据
const consumablesData = ref<ConsumablesStateMessage['data'] | null>(null)
// 修改加载耗材的处理函数
const handleIsLoad = async () => {
  const res = await getInitState()
  if (res.ecode === 'SUC' && !res.data.deviceInited) {
    eventBus.emit('initDevice')
    return
  }
  try {
    isLoading.value = true
    const res = await scanConsumables()
    isLoading.value = false

    // 格式化扫描结果
    formattedReports.value = formatScanReports(res.data.scanReports)
    console.log('🚀 ~ handleIsLoad ~ formattedReports:', formattedReports.value)
    // 显示扫描结果弹窗
    showScanResults.value = true
    consumablesData.value = res.data.consumableState
  } catch (error) {
    console.error('加载耗材失败:', error)
    isLoading.value = false
    isAlreadyLoad.value = false
    ElMessage.error('加载耗材失败')
  }
}
watch(isHandleScan, (newVal) => {
  if (newVal) {
    // 确认后更新状态
    if (consumablesData.value) {
      moveLiquids.value = consumablesData.value.tips
      plates.value = consumablesData.value.reactionPlateGroup as ReactionPlate[]
      bufferLittles.value = consumablesData.value
        .littBottleGroup as BufferLittle[]
      bufferBig.value = consumablesData.value.larBottleGroup as BottleGroup[]
      tempTipNum.value = [...moveLiquids.value.map((liquid) => liquid.tipNum)]
      isLoad.value = true
      isAlreadyLoad.value = true
      consumableStore.setConsumablesData(consumablesData.value)
    }
  } else {
    // 取消时清空临时数据
    consumablesData.value = null
  }
})
const handleIsUnload = () => {
  isLoad.value = !isLoad.value
  isLoading.value = false
  isAlreadyLoad.value = false
  socket.unsubscribe<ConsumablesStateMessage>(
    'ConsumablesStateService',
    handleConsumablesState,
  )
  // 重置 moveLiquids 和 tempTipNum
  moveLiquids.value = [
    { id: 1, tipNum: 0 },
    { id: 2, tipNum: 0 },
    { id: 3, tipNum: 0 },
  ]
  tempTipNum.value = [...moveLiquids.value.map((liquid) => liquid.tipNum)]
  plates.value = []
  emergencyStore.unloadInfo()
  emergencyInfo.value = {} as EmergencyPosStateMessage['data']['tube']
  bufferLittles.value = [
    {
      id: 1,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
    {
      id: 2,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
    {
      id: 3,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
    {
      id: 4,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
    {
      id: 5,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
    {
      id: 6,
      num: 0,
      projShortName: '',
      color: '#4caf50',
    },
  ]
  bufferBig.value = []
}
const updateTipNum = async ({
  index,
  tipNum,
}: {
  index: number
  tipNum: number
}) => {
  // 新临时状态
  tempTipNum.value[index] = tipNum
  console.log('🚀 ~ updateTipNum ~ tempTipNum:', tempTipNum.value)
  //调用接口
  try {
    if (deviceStore.status === 'IDLE') {
      await updateTipsNum({ group: `TipG${index+1}`, num: tipNum })
    } else {
      ElMessage.error('设备正在工作，无法修改数值')
    }
  } catch (error) {
    console.error('修改耗材数量失败:', error)
  }
}
</script>

<style scoped lang="less">
#regular-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;

  .loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9998;
  }

  .loading-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
  }

  .loading-spinner {
    width: 60px;
    height: 60px;
    border: 4px solid #f3f3f3;
    border-top: 4px solid #4caf50;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }

  .loading-text {
    color: white;
    font-size: 24px;
    font-weight: 500;
  }

  .loading-progress {
    width: 300px;
    height: 6px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
    overflow: hidden;
  }

  .progress-bar {
    height: 100%;
    background: #4caf50;
    border-radius: 3px;
    transition: width 0.1s linear;
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }

  .main-top {
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
    height: 100%;

    .plate-area {
      width: 355px;
    }

    .move-liquid-area {
      width: calc(100% - 355px);
    }
  }

  .main-bottom {
    width: 100%;
    flex: 1;
    .buffer-little-title {
      display: flex;
      height: 40px;
      line-height: 40px;
      align-items: center;

      .line {
        width: 4px;
        height: 20px;
        background-color: #4caf50;
        margin: 0 10px 0;
      }

      .content {
        font-size: 26px;
      }
    }

    .ball-area {
      display: flex;
      justify-self: space-between;
      flex-wrap: wrap;

      .ball-grid {
        margin: 0 15px 5px 15px;
      }
    }
  }

  .scan-results-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10000;
    pointer-events: auto;
  }

  .scan-results-container {
    background: white;
    border: 2px solid #ff0000;
    border-radius: 8px;
    width: 800px;
    padding: 20px;
    position: relative;
    z-index: 10001;
    pointer-events: auto;

    .scan-results-header {
      text-align: center;
      margin-bottom: 20px;

      .title {
        color: #ff0000;
        font-size: 32px;
        font-weight: bold;
      }
    }

    .scan-results-content {
      .scan-results-table {
        width: 100%;
        border-collapse: collapse;
        margin: 20px 0;

        th,
        td {
          padding: 15px;
          text-align: left;
          font-size: 24px;
          border-bottom: 1px solid #eee;
        }

        th {
          color: #ff0000;
          font-weight: bold;
          background-color: #fff;
        }

        .error-row {
          background-color: rgba(255, 0, 0, 0.05);
        }

        .error-text {
          color: #ff0000;
        }

        .success-text {
          color: #4caf50;
        }
      }
    }

    .scan-results-footer {
      margin-top: 20px;
      text-align: center;

      .confirm-btn {
        background: #ff0000;
        color: white;
        border: none;
        border-radius: 25px;
        padding: 10px 40px;
        font-size: 24px;
        cursor: pointer;

        &:hover {
          background: darken(#ff0000, 10%);
        }
      }
    }
  }
}
</style>
