<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import type { Hotspot } from '@engine/types'
import { useI18n } from '@/composables/useI18n'

const props = defineProps<{
  hotspots: Hotspot[]
  isImageScene: boolean
  imageUrl?: string | null
  contentSize?: { w: number; h: number } | null
}>()

const { t } = useI18n()

const emit = defineEmits<{
  clickHotspot: [hotspotId: string]
}>()

const layerRef = ref<HTMLDivElement | null>(null)
const layerW = ref(window.innerWidth)
const layerH = ref(window.innerHeight)

function measure() {
  if (layerRef.value) {
    layerW.value = layerRef.value.clientWidth
    layerH.value = layerRef.value.clientHeight
  } else {
    layerW.value = window.innerWidth
    layerH.value = window.innerHeight
  }
}

let resizeObs: ResizeObserver | null = null

onMounted(() => {
  measure()
  resizeObs = new ResizeObserver(() => measure())
  if (layerRef.value) resizeObs.observe(layerRef.value)
  window.addEventListener('resize', measure)
})

onUnmounted(() => {
  resizeObs?.disconnect()
  window.removeEventListener('resize', measure)
})

interface Rect {
  left: string
  top: string
  width: string
  height: string
}

const hotspotRects = computed<Rect[]>(() => {
  const cw = layerW.value
  const ch = layerH.value
  const cs = props.contentSize

  if (!cs || !cs.w || !cs.h) {
    return props.hotspots.map((hs) => ({
      left: `${(hs.x / (cs?.w || 1)) * 100}%`,
      top: `${(hs.y / (cs?.h || 1)) * 100}%`,
      width: `${(hs.width / (cs?.w || 1)) * 100}%`,
      height: `${(hs.height / (cs?.h || 1)) * 100}%`,
    }))
  }

  const scale = Math.min(cw / cs.w, ch / cs.h)
  const renderW = cs.w * scale
  const renderH = cs.h * scale
  const ox = (cw - renderW) / 2
  const oy = (ch - renderH) / 2

  return props.hotspots.map((hs) => ({
    left: `${ox + hs.x * scale}px`,
    top: `${oy + hs.y * scale}px`,
    width: `${hs.width * scale}px`,
    height: `${hs.height * scale}px`,
  }))
})
</script>

<template>
  <div ref="layerRef" class="hotspot-layer" v-if="(hotspots.length > 0) || (isImageScene && imageUrl)">
    <img v-if="isImageScene && imageUrl" :src="imageUrl" class="hotspot-image" />

    <div
      v-for="(hs, i) in hotspots"
      :key="hs.id"
      class="hotspot-rect"
      :style="hotspotRects[i] as any"
      @click.stop="emit('clickHotspot', hs.id)"
      :title="t(hs.labelKey || hs.label)"
      >
      <span class="hotspot-label">{{ t(hs.labelKey || hs.label) }}</span>
    </div>
  </div>
</template>

<style scoped>
.hotspot-layer {
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none;
}

.hotspot-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.hotspot-rect {
  position: absolute;
  border: 2px solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.06);
  border-radius: 4px;
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.15s, border-color 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hotspot-rect:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.8);
}

.hotspot-label {
  font-size: 13px;
  color: #fff;
  background: rgba(0, 0, 0, 0.65);
  padding: 3px 10px;
  border-radius: 3px;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}
</style>
