<script setup lang="ts">
import Konva from 'konva'
import { mapZones, mapConnections, type MapZone } from '~/data/mapZones'

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

const { locale, t } = useI18n()
const router = useRouter()
const localePath = useLocalePath()
const progressionStore = useProgressionStore()
const reducedMotion = useReducedMotion()

const containerRef = ref<HTMLDivElement | null>(null)
const stageRef = ref<Konva.Stage | null>(null)
const animationRef = ref<Konva.Animation | null>(null)

const CANVAS_WIDTH = 800
const CANVAS_HEIGHT = 400

const hoveredZone = ref<MapZone | null>(null)
const tooltipPosition = ref({ x: 0, y: 0 })
const focusedZoneIndex = ref(-1)

onMounted(() => {
  if (containerRef.value) {
    initCanvas()
  }
})

onUnmounted(() => {
  if (animationRef.value) {
    animationRef.value.stop()
  }
  if (stageRef.value) {
    stageRef.value.destroy()
  }
})

function initCanvas() {
  if (!containerRef.value) return

  const stage = new Konva.Stage({
    container: containerRef.value,
    width: CANVAS_WIDTH,
    height: CANVAS_HEIGHT,
  })

  stageRef.value = stage

  const backgroundLayer = new Konva.Layer()
  drawBackground(backgroundLayer)
  stage.add(backgroundLayer)

  const zonesLayer = new Konva.Layer()
  drawZones(zonesLayer)
  stage.add(zonesLayer)

  if (props.currentSection && !reducedMotion.value) {
    const markerLayer = new Konva.Layer()
    drawPositionMarker(markerLayer)
    stage.add(markerLayer)
  }
}

function drawBackground(layer: Konva.Layer) {
  const background = new Konva.Rect({
    x: 0,
    y: 0,
    width: CANVAS_WIDTH,
    height: CANVAS_HEIGHT,
    fill: '#0f172a',
  })
  layer.add(background)

  mapConnections.forEach(([from, to]) => {
    const zoneFrom = mapZones.find((z) => z.id === from)
    const zoneTo = mapZones.find((z) => z.id === to)
    if (zoneFrom && zoneTo) {
      const line = new Konva.Line({
        points: [
          zoneFrom.position.x,
          zoneFrom.position.y,
          zoneTo.position.x,
          zoneTo.position.y,
        ],
        stroke: '#334155',
        strokeWidth: 2,
        dash: [10, 5],
        opacity: 0.5,
      })
      layer.add(line)
    }
  })
}

function drawZones(layer: Konva.Layer) {
  mapZones.forEach((zone) => {
    const isVisited =
      zone.id !== 'contact' && progressionStore.visitedSections.includes(zone.id)
    const isLocked = zone.id === 'contact' && !progressionStore.contactUnlocked

    const group = new Konva.Group({
      x: zone.position.x,
      y: zone.position.y,
    })

    const circle = new Konva.Circle({
      radius: zone.size,
      fill: isLocked ? '#475569' : zone.color,
      opacity: isVisited ? 1 : 0.6,
      shadowColor: zone.color,
      shadowBlur: isVisited ? 20 : 0,
      shadowOpacity: 0.5,
    })
    group.add(circle)

    const icon = new Konva.Text({
      text: isLocked ? '🔒' : zone.emoji,
      fontSize: 32,
      x: -16,
      y: -16,
    })
    group.add(icon)

    if (isVisited && zone.id !== 'contact') {
      const check = new Konva.Text({
        text: '✓',
        fontSize: 24,
        fill: '#22c55e',
        x: zone.size - 25,
        y: -zone.size - 5,
      })
      group.add(check)
    }

    group.on('mouseenter', () => {
      document.body.style.cursor = 'pointer'
      hoveredZone.value = zone
      tooltipPosition.value = {
        x: zone.position.x,
        y: zone.position.y - zone.size - 20,
      }
      circle.shadowBlur(30)
      layer.draw()
    })

    group.on('mouseleave', () => {
      document.body.style.cursor = 'default'
      hoveredZone.value = null
      circle.shadowBlur(isVisited ? 20 : 0)
      layer.draw()
    })

    group.on('click tap', () => {
      handleZoneClick(zone)
    })

    layer.add(group)
  })
}

function drawPositionMarker(layer: Konva.Layer) {
  const currentZone = mapZones.find((z) => z.id === props.currentSection)
  if (!currentZone) return

  const marker = new Konva.Circle({
    x: currentZone.position.x,
    y: currentZone.position.y,
    radius: 10,
    fill: '#fa784f',
    opacity: 1,
  })

  const anim = new Konva.Animation((frame) => {
    if (!frame) return
    const scale = 1 + 0.3 * Math.sin(frame.time / 200)
    marker.scale({ x: scale, y: scale })
    marker.opacity(1 - 0.3 * Math.abs(Math.sin(frame.time / 200)))
  }, layer)

  animationRef.value = anim
  anim.start()
  layer.add(marker)
}

function handleZoneClick(zone: MapZone) {
  if (zone.id === 'contact' && !progressionStore.contactUnlocked) {
    return
  }

  const route = locale.value === 'fr' ? zone.route.fr : zone.route.en
  router.push(route)
}

function handleKeydown(e: KeyboardEvent) {
  if (e.key === 'Tab') {
    e.preventDefault()
    if (e.shiftKey) {
      focusedZoneIndex.value =
        (focusedZoneIndex.value - 1 + mapZones.length) % mapZones.length
    } else {
      focusedZoneIndex.value = (focusedZoneIndex.value + 1) % mapZones.length
    }
    highlightFocusedZone()
  } else if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault()
    if (focusedZoneIndex.value >= 0) {
      handleZoneClick(mapZones[focusedZoneIndex.value])
    }
  }
}

function highlightFocusedZone() {
  const zone = mapZones[focusedZoneIndex.value]
  hoveredZone.value = zone
  tooltipPosition.value = {
    x: zone.position.x,
    y: zone.position.y - zone.size - 20,
  }
}

function getZoneStatus(zone: MapZone): string {
  if (zone.id === 'contact' && !progressionStore.contactUnlocked) {
    return t('map.locked')
  }
  if (zone.id !== 'contact' && progressionStore.visitedSections.includes(zone.id)) {
    return t('map.visited')
  }
  return t('map.clickToExplore')
}
</script>

<template>
  <div
    class="interactive-map-container relative"
    tabindex="0"
    role="application"
    :aria-label="t('map.ariaLabel')"
    @keydown="handleKeydown"
  >
    <div
      ref="containerRef"
      class="konva-container rounded-xl overflow-hidden shadow-2xl border border-sky-dark-100"
    />

    <Transition name="fade">
      <div
        v-if="hoveredZone"
        class="tooltip absolute pointer-events-none z-10 bg-sky-dark-50 border border-sky-dark-100 rounded-lg px-3 py-2 shadow-lg"
        :style="{
          left: `${tooltipPosition.x}px`,
          top: `${tooltipPosition.y}px`,
          transform: 'translate(-50%, -100%)',
        }"
      >
        <p class="font-ui font-semibold text-sky-text">
          {{ locale === 'fr' ? hoveredZone.label.fr : hoveredZone.label.en }}
        </p>
        <p class="text-xs text-sky-text-muted">
          {{ getZoneStatus(hoveredZone) }}
        </p>
        <div
          class="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-sky-dark-50 border-r border-b border-sky-dark-100 transform rotate-45"
        />
      </div>
    </Transition>

    <div
      class="legend absolute bottom-4 left-4 bg-sky-dark-50/80 backdrop-blur rounded-lg p-3"
    >
      <div class="flex items-center gap-4 text-xs font-ui">
        <div class="flex items-center gap-1.5">
          <span class="w-3 h-3 rounded-full bg-sky-accent opacity-60" />
          <span class="text-sky-text-muted">{{ t('map.legend.notVisited') }}</span>
        </div>
        <div class="flex items-center gap-1.5">
          <span
            class="w-3 h-3 rounded-full bg-sky-accent shadow-lg"
            style="box-shadow: 0 0 10px var(--sky-accent)"
          />
          <span class="text-sky-text-muted">{{ t('map.legend.visited') }}</span>
        </div>
        <div class="flex items-center gap-1.5">
          <span class="w-3 h-3 rounded-full bg-gray-500" />
          <span class="text-sky-text-muted">{{ t('map.legend.locked') }}</span>
        </div>
      </div>
    </div>

    <p class="sr-only">
      {{ t('map.instructions') }}
    </p>
  </div>
</template>

<style scoped>
.interactive-map-container {
  width: 800px;
  height: 400px;
}

.interactive-map-container:focus {
  outline: 2px solid var(--sky-accent);
  outline-offset: 4px;
  border-radius: 0.75rem;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.15s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .fade-enter-active,
  .fade-leave-active {
    transition: none;
  }
}
</style>
