<template>
  <div>
    <div class="time-card">
      <i class="el-icon-time"></i>
      <div class="time-content">
        <div class="label">最后更新</div>
        <div class="time">{{ updateTime }}</div>
      </div>
    </div>
    <div ref="container" style="width: 900px; height: 400px;margin: 0 auto"></div>

    <el-dialog title="异常信息" :visible.sync="dialogVisible" width="400px">
      <h4 style="text-align: center; font-weight: bolder">{{ errorInfo }}</h4>
      <div slot="footer" class="dialog-footer">
        <el-button v-no-more-click @click="cancel">关 闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import Konva from 'konva'
import { getIsSystemAttributeByKey } from '@/api/system/configuration'
import { getIsLockCabinetSlotsPage } from '@/api/mes/lockCabinet/slots'

export default {
  data() {
    return {
      stage: null,
      layer: null,
      cachedResults: {},
      cachedImages: {},
      slotData: [],
      dialogVisible: false,
      errorInfo: '',
      updateTime: null
    }
  },
  mounted() {
    this.initKonva()
    this.getData()
  },
  methods: {
    cancel() {
      this.dialogVisible = false
    },
    async getData() {
      const data = {
        current: 1,
        size: -1,
        cabinetId: this.$route.query.cabinetId
      }
      try {
        const res = await getIsLockCabinetSlotsPage(data)
        this.updateTime = res.data.records[0].updateTime
        this.slotData = res.data?.records || []

        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)))
        this.cachedResults = icons.reduce((map, key, idx) => {
          map[key] = results[idx].data?.sysAttrValue || ''
          return map
        }, {})

        await this.preloadImages()
        this.renderSlots()
      } catch (err) {
        console.error('获取数据失败:', err)
      }
    },
    showErrorDialog(slot) {
      this.errorInfo = slot.remark || '未知异常'
      this.dialogVisible = true
    },
    initKonva() {
      this.stage = new Konva.Stage({
        container: this.$refs.container,
        width: 900,
        height: 800
      })
      this.layer = new Konva.Layer()
      this.stage.add(this.layer)
    },
    async preloadImages() {
      const urls = Object.values(this.cachedResults)
      const promises = urls.map(url => this.loadImageOnce(url))
      await Promise.all(promises)
    },
    async renderSlots() {
      this.layer.destroyChildren()
      const grouped = {}
      for (const slot of this.slotData) {
        const key = `${slot.row}`
        if (!grouped[key]) grouped[key] = []
        grouped[key].push(slot)
      }

      const rows = Object.keys(grouped).sort((a, b) => Number(a) - Number(b))
      const startY = 20
      const rowHeight = 120
      const rowGap = 20

      for (let i = 0; i < rows.length; i++) {
        const rowSlots = grouped[rows[i]]
        await this.renderSlotRow(rowSlots, startY + i * (rowHeight + rowGap), rowHeight)
      }

      this.layer.draw()
    },
    async renderSlotRow(slots, boxTopY, boxHeight) {
      const padding = 20
      const boxWidth = 860
      const centerX = this.stage.width() / 2
      const boxStartX = centerX - boxWidth / 2

      const box = new Konva.Rect({
        x: boxStartX,
        y: boxTopY,
        width: boxWidth,
        height: boxHeight,
        stroke: 'black',
        strokeWidth: 2
      })
      this.layer.add(box)

      const loadedImages = []
      for (const slot of slots) {
        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 = this.cachedResults[baseKey]
        if (!baseUrl || !this.cachedImages[baseUrl]) continue

        const imageNode = this.cachedImages[baseUrl].clone()
        const width = slotType === '0' ? 110 : 40
        const height = 90
        imageNode.setAttrs({ width, height })

        loadedImages.push({ imageNode, slot, width, height })
      }

      const totalSlots = loadedImages.length
      const spacing = totalSlots > 1
        ? (boxWidth - 2 * padding - totalSlots * loadedImages[0].width) / (totalSlots - 1)
        : 0
      let currentX = boxStartX + padding

      for (const { imageNode, slot, width, height } of loadedImages) {
        imageNode.setAttrs({
          x: currentX,
          y: boxTopY + (boxHeight - height) / 2
        })
        this.layer.add(imageNode)

        if (slot.status === '1') {
          const exUrl = this.cachedResults['icon.locker.exception']
          if (exUrl && this.cachedImages[exUrl]) {
            const exImage = this.cachedImages[exUrl].clone()
            const exWidth = 30
            const exHeight = 30
            exImage.setAttrs({
              x: currentX + (width - exWidth) / 2,
              y: boxTopY + (boxHeight - exHeight) / 2,
              width: exWidth,
              height: exHeight
            })
            exImage.on('click', () => {
              this.showErrorDialog(slot)
            })
            this.layer.add(exImage)
          }
        }

        currentX += width + spacing
      }
    },
    loadImageOnce(url) {
      if (this.cachedImages[url]) return Promise.resolve(this.cachedImages[url])

      return new Promise((resolve, reject) => {
        const img = new window.Image()
        img.crossOrigin = 'Anonymous'
        img.src = url
        img.onload = () => {
          const konvaImage = new Konva.Image({ image: img })
          this.cachedImages[url] = konvaImage
          resolve(konvaImage)
        }
        img.onerror = reject
      })
    }
  }
}
</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;
}
.time-card.glow {
  box-shadow: 0 0 15px rgba(64, 158, 255, 0.5);
}
.time-card i {
  font-size: 24px;
  color: #409EFF;
  margin-right: 12px;
}
.time-content .label {
  font-size: 12px;
  color: #909399;
}
.time-content .time {
  font-size: 16px;
  font-weight: bold;
  color: #303133;
}
</style>
