<template>
  <ContentWrap>
    <div class="time-card">
      <Icon icon="ep:timer" class="mr-5px"  :size="35"/>
      <div class="time-content">
        <div class="label">最后更新</div>
        <div class="time">{{ updateTime }}</div>
      </div>
    </div>

    <div class="map-container">
      <v-stage :config="stageConfig" ref="stageRef">
        <v-layer ref="layerRef">
          <!-- 动态渲染仓位行 -->
          <template v-for="(rowSlots, rowIndex) in groupedSlots" :key="rowIndex">
            <!-- 行容器 -->
            <v-rect :config="getRowBoxConfig(rowIndex)" />

            <!-- 仓位图标 -->
            <template v-for="(slot, slotIndex) in rowSlots" :key="`${rowIndex}-${slotIndex}`">
              <v-image
                :config="getSlotImageConfig(slot, rowIndex, slotIndex, rowSlots)"
                @click="handleSlotClick(slot)"
              />

              <!-- 异常图标 -->
              <v-image
                v-if="slot.status === '1'"
                :config="getExceptionImageConfig(slot, rowIndex, slotIndex, rowSlots)"
                @click="showErrorDialog(slot)"
              />
            </template>
          </template>
        </v-layer>
      </v-stage>
    </div>

    <Dialog v-model="dialogVisible" title="异常信息" width="400">
      <h4 class="text-center font-bold">{{ errorInfo }}</h4>
      <template #footer>
        <el-button @click="dialogVisible = false">关 闭</el-button>
      </template>
    </Dialog>
  </ContentWrap>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue'
import { getIsSystemAttributeByKey } from '@/api/basic/configuration/index'
import { getIsLockCabinetSlotsPage } from '@/api/hw/hardware/lockCabinet/slots'
import { formatDate } from '@/utils/formatTime'
defineOptions({ name: 'LockCabinetMap' })

const props = defineProps<{
  cabinetId: string
}>()

const stageRef = ref()
const layerRef = ref()
const cachedResults = ref<Record<string, string>>({})
const cachedImages = ref<Record<string, HTMLImageElement>>({})
const slotData = ref<any[]>([])
const dialogVisible = ref(false)
const errorInfo = ref('')
const updateTime = ref<string | null>(null)

// Stage 配置
const stageConfig = {
  width: 900,
  height: 1000
}

// 计算属性：按行分组仓位数据
const groupedSlots = computed(() => {
  const grouped: Record<string, any[]> = {}
  for (const slot of slotData.value) {
    const key = `${slot.row}`
    if (!grouped[key]) grouped[key] = []
    grouped[key].push(slot)
  }

  // 按行号排序
  return Object.keys(grouped)
    .sort((a, b) => Number(a) - Number(b))
    .map(rowKey => grouped[rowKey])
})

// 获取行容器配置
const getRowBoxConfig = (rowIndex: number) => {
  const startY = 20
  const rowHeight = 120
  const rowGap = 20
  const boxWidth = 860
  const centerX = stageConfig.width / 2
  const boxStartX = centerX - boxWidth / 2

  return {
    x: boxStartX,
    y: startY + rowIndex * (rowHeight + rowGap),
    width: boxWidth,
    height: rowHeight,
    stroke: 'black',
    strokeWidth: 2,
    fill: 'transparent'
  }
}

// 获取仓位图标配置
const getSlotImageConfig = (slot: any, rowIndex: number, slotIndex: number, rowSlots: any[]) => {
  const { slotType, isOccupied } = slot
  let baseKey = ''

  if (slotType === '0') {
    baseKey = isOccupied === '1' ? 'icon.locker.normal' : 'icon.locker.out'
  } else {
    baseKey = isOccupied === '1' ? 'icon.padlock.normal' : 'icon.padlock.out'
  }

  const baseUrl = cachedResults.value[baseKey]
  if (!baseUrl || !cachedImages.value[baseUrl]) {
    return null
  }

  const width = slotType === '0' ? 110 : 40
  const height = 90
  const startY = 20
  const rowHeight = 120
  const rowGap = 20
  const padding = 20
  const boxWidth = 860
  const centerX = stageConfig.width / 2
  const boxStartX = centerX - boxWidth / 2

  // 计算位置
  const totalSlots = rowSlots.length
  const spacing = totalSlots > 1
    ? (boxWidth - 2 * padding - totalSlots * width) / (totalSlots - 1)
    : 0

  const x = boxStartX + padding + slotIndex * (width + spacing)
  const y = startY + rowIndex * (rowHeight + rowGap) + (rowHeight - height) / 2
  return {
    x,
    y,
    width,
    height,
    image: cachedImages.value[baseUrl],
    listening: true
  }
}

// 获取异常图标配置
const getExceptionImageConfig = (slot: any, rowIndex: number, slotIndex: number, rowSlots: any[]) => {
  const exUrl = cachedResults.value['icon.locker.exception']
  console.log('getExceptionImageConfig', exUrl)
  if (!exUrl || !cachedImages.value[exUrl]) {
    return null
  }

  const slotConfig = getSlotImageConfig(slot, rowIndex, slotIndex, rowSlots)
  if (!slotConfig) return null

  const exWidth = 30
  const exHeight = 30

  return {
    x: slotConfig.x + (slotConfig.width - exWidth) / 2,
    y: slotConfig.y + (slotConfig.height - exHeight) / 2,
    width: exWidth,
    height: exHeight,
    image: cachedImages.value[exUrl],
    listening: true
  }
}

// 获取数据
const getData = async () => {
  const data = {
    pageNo: 1,
    pageSize: -1,
    cabinetId: props.cabinetId
  }

  try {
    const res = await getIsLockCabinetSlotsPage(data)

    updateTime.value = formatDate(res.list[0].createTime)
    slotData.value = res.list || []
    const icons = [
      'icon.locker.normal',
      'icon.locker.out',
      'icon.padlock.normal',
      'icon.padlock.out',
      'icon.locker.exception'
    ]

    const results = await Promise.all(icons.map(key => getIsSystemAttributeByKey(key)))
    cachedResults.value = icons.reduce((map, key, idx) => {
      map[key] = results[idx].sysAttrValue || ''
      return map
    }, {} as Record<string, string>)

    await preloadImages()
  } catch (err) {
    console.error('获取数据失败:', err)
  }
}

// 显示错误对话框
const showErrorDialog = (slot: any) => {
  errorInfo.value = slot.remark || '未知异常'
  dialogVisible.value = true
}

// 处理仓位点击
const handleSlotClick = (slot: any) => {
  console.log('点击仓位:', slot)
  // 可以在这里添加仓位点击逻辑
}

// 预加载图片
const preloadImages = async () => {

  const urls = Object.values(cachedResults.value)
  const promises = urls.map(url => loadImageOnce(url))
  await Promise.all(promises)
}

// 加载图片
const loadImageOnce = (url: string) => {
  if (cachedImages.value[url]) {
    return Promise.resolve(cachedImages.value[url])
  }

  return new Promise<HTMLImageElement>((resolve, reject) => {
    const img = new window.Image()
    img.crossOrigin = 'Anonymous'
    img.src = url
    img.onload = () => {
      cachedImages.value[url] = img
      resolve(img)
    }
    img.onerror = reject
  })
}

// 初始化
onMounted(async () => {
  await getData()
})
</script>

<style scoped lang="scss">
.time-card {
  display: inline-flex;
  align-items: center;
  padding: 12px 20px;
  background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s;
  .mr-5px {
    font-size: 20px;
    color: rgb(64, 158, 254);
  }
  &.glow {
    box-shadow: 0 0 15px rgba(64, 158, 255, 0.5);
  }

  .time-content {
    .label {
      font-size: 12px;
      color: #909399;
    }
    .time {
      font-size: 16px;
      font-weight: bold;
      color: #303133;
    }
  }
}

.map-container {
  width: 900px;
  height: 800px;
  margin: 0 auto;
}
</style>
