<template>
  <a-spin :spinning="spinning">
    <div class="deviceDetail">
      <div class="radarMap">
        <info-card title="房间监测">
          <template #extra>
            <a-button type="primary" size="small" @click="roomConfigHandler('area')">
              区域配置
            </a-button>
          </template>
          <div
            class="radarBox"
            :style="{
              width: `${detailState?.length}px`,
              height: `${detailState?.width}px`,
            }"
          >
            <template v-if="targets && Object.keys(targets).length > 0">
              <template v-for="t in targets" :key="t.id">
                <div
                  class="target-dot"
                  :style="{
                    position: 'absolute',
                    width: '18px',
                    height: '18px',
                    background: t.id === 0 ? 'red' : t.id === 1 ? 'blue' : 'green',
                    borderRadius: '50%',
                    transform: `translate3d(${t.displayX + 200}px, ${-t.displayY + 200}px, 0) translate(-50%, -50%)`,
                    zIndex: 10,
                    transition: 'transform 1s linear',
                    willChange: 'transform',
                  }"
                >
                  <span
                    style="
                      color: #fff;
                      font-size: 12px;
                      font-weight: 600;
                      position: absolute;
                      left: 50%;
                      top: 50%;
                      transform: translate(-50%, -50%);
                      pointer-events: none;
                    "
                  >
                    {{ t.id + 1 }}
                  </span>
                </div>
              </template>
            </template>
            <div>
              <furniture-icon
                v-for="(item, index) in furnitureItems"
                :key="index"
                :icon="item.type"
                :width="item.width"
                :height="item.length"
                :style="{
                  left: `${item.left}px`,
                  top: `${item.top}px`,
                  position: 'absolute',
                  rotate: `${item.rotate}deg`,
                  cursor: 'default',
                  pointerEvents: 'none',
                }"
                :draggable="false"
              />
            </div>
          </div>
        </info-card>
      </div>

      <div class="infos">
        <info-card title="基本信息">
          <template #extra>
            <a-button type="primary" size="small" @click="roomConfigHandler('base')">
              设备配置
            </a-button>
          </template>
          <info-item label="设备ID">{{ detailState.clientId }}</info-item>
          <info-item label="设备名称">{{ detailState.devName }}</info-item>
          <info-item label="设备类型">{{ detailState.devType }}</info-item>
          <info-item label="固件版本号">{{ detailState.hardware }}</info-item>
          <info-item label="激活日期">{{ detailState.activeTime }}</info-item>
          <info-item label="在离线状态">
            <a-tag
              v-if="detailState.online === 0"
              :bordered="false"
              :color="deviceOnlineStateMap[detailState.online].color"
              >{{ deviceOnlineStateMap[detailState.online].name }}</a-tag
            >
            <a-tag
              v-if="detailState.online === 1"
              :bordered="false"
              :color="deviceOnlineStateMap[detailState.online].color"
              >{{ deviceOnlineStateMap[detailState.online].name }}</a-tag
            >
          </info-item>
          <info-item label="归属租户">{{ detailState.tenantName }}</info-item>
          <info-item label="统计信息">
            <a-button type="link" size="small" @click="viewDeviceHistoryInfo"> 点击查看 </a-button>
          </info-item>
        </info-card>

        <info-card title="安装参数">
          <info-item label="安装高度">
            <template v-if="detailState.height"> {{ detailState.height }} cm</template>
          </info-item>
          <info-item label="检测区域">
            <template v-if="detailState.length || detailState.width">
              {{ detailState.length || 0 }} x {{ detailState.width || 0 }} cm
            </template>
          </info-item>
          <info-item label="安装位置">
            {{
              deviceInstallPositionNameMap[
                detailState.installPosition as keyof typeof deviceInstallPositionNameMap
              ]
            }}
          </info-item>
        </info-card>
      </div>

      <deviceConfigDrawer
        v-model:open="configDrawerOpen"
        :data="{
          devId: (detailState.devId as string) || '',
          clientId: (detailState.clientId as string) || '',
          length: (detailState.length as number) || 0,
          width: (detailState.width as number) || 0,
        }"
        :mode="configDrawerMode"
        :room-id="deviceRoomId"
        :furniture-items="furnitureItems"
        :sub-region-items="subRegionItems"
        @success="saveConfigSuccess"
      ></deviceConfigDrawer>

      <deviceStatsDrawer
        v-model:open="statsDrawerOpen"
        :dev-id="`${detailState.devId as string}`"
        :title="`${detailState.devName} 统计信息`"
      ></deviceStatsDrawer>
    </div>
  </a-spin>
</template>

<script setup lang="ts">
import infoCard from './components/infoCard/index.vue'
import infoItem from './components/infoItem/index.vue'
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { useRoute } from 'vue-router'
import { message } from 'ant-design-vue'
import * as roomApi from '@/api/room'
import type { Furniture } from '@/api/room/types'
import mqtt, { MqttClient } from 'mqtt'
import * as deviceApi from '@/api/device'
import type { DeviceDetailData } from '@/api/device/types'
import { deviceOnlineStateMap, deviceInstallPositionNameMap } from '@/const/device'
import deviceConfigDrawer from './components/deviceConfig/index.vue'
import deviceStatsDrawer from './components/deviceStatsDrawer/index.vue'

defineOptions({
  name: 'DeviceDetail',
})

const route = useRoute()
const devId = ref<string>((route.query.devId as string) || '') // 设备id
const clientId = ref<string>((route.query.clientId as string) || '') // 设备id

interface BlockItem {
  startXx: number // 屏蔽子区域X开始
  stopXx: number // 屏蔽子区域X结束
  startYy: number // 屏蔽子区域Y开始
  stopYy: number // 屏蔽子区域Y结束
  startZz: number // 屏蔽子区域Z开始
  stopZz: number // 屏蔽子区域Z结束
  isLowSnr: number // 默认0
  isDoor: number // 是否是门 0-否,1-是 默认0
  presenceEnterDuration: number // 	人员进入时间 默认3
  presenceExitDuration: number // 人员离开时间 默认3
  trackPresence: number // 是否开启区域跟踪存在 0-否,1-是
  excludeFalling: number // 是否屏蔽区域跌倒检测 0-否,1-是
}

const deviceRoomId = ref<string>('')
const furnitureItems = ref<Furniture[]>([])
const subRegionItems = ref<BlockItem[]>([])
/**
 * 获取房间布局
 */
const fetchRoomLayout = async () => {
  console.log('fetchRoomLayout', devId.value)
  if (!devId.value) {
    message.error('设备ID不能为空')
    return
  }
  try {
    const res = await roomApi.queryRoomInfo({
      devId: devId.value,
    })
    console.log('✅获取到房间布局信息', res)
    if (!res) return
    const { furnitures, roomId, subRegions } = res.data
    if (furnitures) {
      furnitureItems.value = furnitures!.map((item) => {
        return {
          ...item,
          width: item.width || 45,
          length: item.length || 45,
          top: item.top || 0,
          left: item.left || 0,
          rotate: item.rotate || 0,
          x: item.x || 0,
          y: item.y || 0,
        }
      })
    }
    deviceRoomId.value = roomId || ''
    subRegionItems.value = subRegions || []
  } catch (error) {
    console.error('❌获取房间布局信息失败', error)
  }
}
fetchRoomLayout()

const detailState = ref<DeviceDetailData>({
  devId: '',
  clientId: '',
  userId: '',
  devName: '',
  devType: '',
  online: 0,
  devWarn: 0,
  software: '',
  hardware: '',
  wifiName: '',
  wifiPassword: '',
  ip: '',
  mountPlain: 'Wall',
  installPosition: 'Toilet',
  xxStart: 0,
  xxEnd: 0,
  yyStart: 0,
  yyEnd: 0,
  zzStart: 0,
  zzEnd: 0,
  height: 0,
  length: 0,
  width: 0,
  targetPoints: [],
  signalTime: 0,
  northAngle: 0,
  activeTime: '',
  statusLight: 0,
  createId: '',
  updateId: '',
  createTime: '',
  updateTime: '',
  tenantName: '',
  tenantId: '',
  fallingConfirm: null,
})

const spinning = ref(false)
// 获取设备详情
const fetchDeviceDetail = async () => {
  console.log('fetchDeviceDetail', devId.value)
  if (!devId.value) {
    message.error('设备ID不能为空')
    return
  }
  try {
    spinning.value = true
    const res = await deviceApi.getDeviceDetailByDevId({
      devId: devId.value,
    })
    console.log('✅获取到设备详情', res)
    detailState.value = res.data
    spinning.value = false
  } catch (error) {
    console.error('❌获取设备详情失败', error)
    spinning.value = false
  }
}
fetchDeviceDetail()

const saveConfigSuccess = () => {
  setTimeout(() => {
    fetchDeviceDetail()
    fetchRoomLayout()
  }, 1000)
}

const configDrawerOpen = ref(false)
const configDrawerMode = ref<'base' | 'area'>('base')
const roomConfigHandler = (type: 'base' | 'area') => {
  configDrawerMode.value = type
  configDrawerOpen.value = true
}

const statsDrawerOpen = ref(false)
// 查看设备历史信息
const viewDeviceHistoryInfo = () => {
  console.log('viewDeviceHistoryInfo')
  statsDrawerOpen.value = true
}

interface TargetInfo {
  x: number
  y: number
  z: number
  id: number
  displayX: number
  displayY: number
  lastX: number
  lastY: number
}

const targets = reactive<Record<number, TargetInfo>>({}) // 以id为key
const THRESHOLD = 2 // 去抖阈值

let mqttClient: MqttClient | null = null
let mqttTimeout: number | null = null
const MQTT_TIMEOUT_MS = 1000 // 调整为1秒

const resetMqttTimeout = () => {
  if (mqttTimeout) clearTimeout(mqttTimeout)
  mqttTimeout = window.setTimeout(() => {
    Object.keys(targets).forEach((key) => delete targets[Number(key)])
    console.log('MQTT超时未收到新消息，隐藏所有红点')
  }, MQTT_TIMEOUT_MS)
}

onMounted(() => {
  console.log('onMounted', mqttClient)
  const mqttConfig = {
    host: import.meta.env.VITE_MQTT_HOST,
    username: import.meta.env.VITE_MQTT_USERNAME,
    password: import.meta.env.VITE_MQTT_PASSWORD,
    clientId: `mqtt_client_${Math.random().toString(16).slice(2, 8)}`,
  }
  mqttClient = mqtt.connect(mqttConfig.host, {
    clientId: mqttConfig.clientId,
    username: mqttConfig.username,
    password: mqttConfig.password,
  })
  console.log('mqttClient connect ready', mqttClient)
  mqttClient.on('connect', () => {
    console.log('MQTT已连接')
    // 订阅所有设备的主题
    mqttClient?.subscribe(`/mps/${clientId.value}/realtime_pos`, (err) => {
      if (err) {
        console.error('MQTT订阅失败', err)
      } else {
        console.log(`已订阅主题 /mps/${clientId.value}/realtime_pos`)
      }
    })
  })
  mqttClient.on('error', (err) => {
    console.error('MQTT连接错误', err)
  })
  mqttClient.on('message', (topic: string, message: Uint8Array) => {
    resetMqttTimeout()
    const match = topic.match(/^\/mps\/(.+)\/realtime_pos$/)
    if (!match) return
    const msgDevId = match[1]
    if (msgDevId !== clientId.value) return // 只处理当前设备
    try {
      const data = JSON.parse(message.toString())
      const arr = data.targetPoints
      console.log('收到MQTT消息', data, data.targetPoints)
      if (Array.isArray(arr) && arr.length > 0 && Array.isArray(arr[0])) {
        // 记录本次出现的所有id
        const currentIds = new Set<number>()
        arr.forEach((item: number[]) => {
          if (item.length < 4) return
          const [x, y, z, id] = item
          currentIds.add(id)
          if (!(id in targets)) {
            targets[id] = { x, y, z, id, displayX: x, displayY: y, lastX: x, lastY: y }
          }
          // 去抖动
          const dx = x - targets[id].lastX
          const dy = y - targets[id].lastY
          if (Math.sqrt(dx * dx + dy * dy) > THRESHOLD) {
            targets[id].x = x
            targets[id].y = y
            targets[id].z = z
            targets[id].lastX = x
            targets[id].lastY = y
            targets[id].displayX = x
            targets[id].displayY = y
            console.log(`更新目标点: id=${id}, x=${x}, y=${y}`, targets[id])
          } else {
            // 距离太小，忽略本次更新
            // console.log(`忽略微小抖动 id=${id}`)
          }
        })
        // 删除本次未出现的id
        Object.keys(targets).forEach((key) => {
          const id = Number(key)
          if (!currentIds.has(id)) {
            delete targets[id]
            // console.log(`ID=${id} 消失，隐藏对应红点`)
          }
        })
      } else {
        // 没有目标时，隐藏所有红点
        Object.keys(targets).forEach((key) => delete targets[Number(key)])
        // console.log('tracker_targets为空，隐藏所有红点')
      }
    } catch (e) {
      console.error('MQTT消息解析失败', e)
    }
  })
})

onUnmounted(() => {
  if (mqttClient) mqttClient.end()
  if (mqttTimeout) clearTimeout(mqttTimeout)
})
</script>

<style scoped lang="less">
.deviceDetail {
  background-color: #fff;
  display: flex;
  justify-content: space-between;
  min-height: 500px;
  padding: 20px;

  .radarMap {
    flex-shrink: 0;
    margin-right: 16px;
    min-width: 400px;
    min-height: 400px;
    background-color: #f5f5f5;
    border-radius: 10px;

    :deep(.info) {
      &-content {
        align-items: center !important;
      }
    }

    .radarBox {
      position: relative;
      background-image:
        linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
        linear-gradient(to right, rgba(0, 0, 0, 0.1) 1px, transparent 1px);
      background-size: 20px 20px;
      border: 1px solid rgba(0, 0, 0, 0.8);
      overflow: hidden;

      .furniture-item {
        position: absolute;
        user-select: none;
        cursor: move;
        width: 30px;
        height: 30px;
      }
    }
  }

  .infos {
    flex-grow: 1;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
  }
}
</style>
