<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import { cn } from '@/lib/utils'
import Button from '@/components/shared/Button.vue'
import { useLocalTranslation } from '@/lib/composables/useLocalTranslation'
import MaterialSymbolsCloseSmallOutlineRounded from '~icons/material-symbols/close-small-outline-rounded'
import SolarArrowRightBoldDuotone from '~icons/solar/arrow-right-bold-duotone'

const props = withDefaults(
  defineProps<{
    imageUrls: string[]
    initialIndex: number
    isOpen: boolean
    alt?: string
  }>(),
  { alt: 'Preview' }
)

const emit = defineEmits<{ close: [] }>()

const { dir } = useLocalTranslation()
const currentIndex = ref(props.initialIndex)
const zoomLevel = ref(1)
const imagePosition = ref({ x: 0, y: 0 })
const isDragging = ref(false)
const dragStart = ref({ x: 0, y: 0 })

const currentImageUrl = computed(() => props.imageUrls[currentIndex.value])
const hasMultipleImages = computed(() => props.imageUrls.length > 1)

watch(
  () => [props.isOpen, props.initialIndex] as const,
  ([open, idx]) => {
    if (open) {
      currentIndex.value = idx
      zoomLevel.value = 1
      imagePosition.value = { x: 0, y: 0 }
    }
  }
)

watch(zoomLevel, (v) => {
  if (v <= 1) imagePosition.value = { x: 0, y: 0 }
})

watch(
  () => props.isOpen,
  (open) => {
    document.body.style.overflow = open ? 'hidden' : 'unset'
  }
)

onUnmounted(() => { document.body.style.overflow = 'unset' })

function handlePrevious() {
  if (currentIndex.value > 0) { currentIndex.value--; zoomLevel.value = 1; imagePosition.value = { x: 0, y: 0 } }
}
function handleNext() {
  if (currentIndex.value < props.imageUrls.length - 1) { currentIndex.value++; zoomLevel.value = 1; imagePosition.value = { x: 0, y: 0 } }
}
function handleZoomIn() { zoomLevel.value = Math.min(zoomLevel.value + 0.25, 3) }
function handleZoomOut() { zoomLevel.value = Math.max(zoomLevel.value - 0.25, 0.5) }
function handleResetZoom() { zoomLevel.value = 1; imagePosition.value = { x: 0, y: 0 } }
function handleClose() { zoomLevel.value = 1; imagePosition.value = { x: 0, y: 0 }; emit('close') }

async function handleDownload() {
  if (!currentImageUrl.value) return
  try {
    const response = await fetch(currentImageUrl.value)
    const blob = await response.blob()
    const blobUrl = URL.createObjectURL(blob)
    const urlParts = currentImageUrl.value.split('/')
    const filename = urlParts[urlParts.length - 1].split('?')[0] || 'image.png'
    const link = document.createElement('a')
    link.href = blobUrl
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(blobUrl)
  } catch {
    window.open(currentImageUrl.value, '_blank')
  }
}

function handleWheel(e: WheelEvent) {
  if (e.ctrlKey || e.metaKey) {
    e.preventDefault()
    e.deltaY < 0 ? handleZoomIn() : handleZoomOut()
  }
}

function handleMouseDown(e: MouseEvent) {
  if (zoomLevel.value > 1) {
    isDragging.value = true
    dragStart.value = { x: e.clientX - imagePosition.value.x, y: e.clientY - imagePosition.value.y }
  }
}

function handleMouseMove(e: MouseEvent) {
  if (isDragging.value && zoomLevel.value > 1) {
    imagePosition.value = { x: e.clientX - dragStart.value.x, y: e.clientY - dragStart.value.y }
  }
}

function handleMouseUp() { isDragging.value = false }

function handleKeyDown(e: KeyboardEvent) {
  if (!props.isOpen) return
  const isRtl = dir.value === 'rtl'
  if (e.key === 'ArrowLeft') { e.preventDefault(); isRtl ? handleNext() : handlePrevious() }
  else if (e.key === 'ArrowRight') { e.preventDefault(); isRtl ? handlePrevious() : handleNext() }
  else if (e.key === 'Escape') { e.preventDefault(); handleClose() }
  else if (e.key === '+' || e.key === '=') { e.preventDefault(); handleZoomIn() }
  else if (e.key === '-') { e.preventDefault(); handleZoomOut() }
  else if (e.key === '0') { e.preventDefault(); handleResetZoom() }
}

onMounted(() => window.addEventListener('keydown', handleKeyDown))
onUnmounted(() => window.removeEventListener('keydown', handleKeyDown))
</script>

<template>
  <div
    v-if="isOpen && currentImageUrl"
    class="babylai:fixed babylai:inset-0 babylai:z-[9999] babylai:flex babylai:items-center babylai:justify-center"
    role="dialog"
    aria-modal="true"
    aria-label="Image preview dialog"
    @click="handleClose"
  >
    <div class="babylai:absolute babylai:inset-0 babylai:bg-black babylai:bg-opacity-95" />

    <div
      class="babylai:relative babylai:w-full babylai:h-full babylai:flex babylai:items-center babylai:justify-center babylai:overflow-hidden"
      @click.stop
      @wheel="handleWheel"
      @mousedown="handleMouseDown"
      @mousemove="handleMouseMove"
      @mouseup="handleMouseUp"
      @mouseleave="handleMouseUp"
    >
      <!-- Close Button -->
      <Button
        variant="ghost"
        size="icon"
        :class="cn(
          'babylai:absolute babylai:top-4 babylai:z-[60]',
          dir === 'rtl' ? 'babylai:left-4' : 'babylai:right-4',
          'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-10 babylai:w-10 babylai:rounded-full'
        )"
        aria-label="Close preview"
        @click="handleClose"
      >
        <MaterialSymbolsCloseSmallOutlineRounded class="babylai:w-6 babylai:h-6" />
      </Button>

      <!-- Navigation Buttons -->
      <template v-if="hasMultipleImages">
        <Button
          variant="ghost"
          size="icon"
          :disabled="dir === 'rtl' ? currentIndex === imageUrls.length - 1 : currentIndex === 0"
          :class="cn(
            'babylai:absolute babylai:top-1/2 babylai:-translate-y-1/2 babylai:z-[60]',
            dir === 'rtl' ? 'babylai:right-4' : 'babylai:left-4',
            'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-12 babylai:w-12 babylai:rounded-full babylai:disabled:opacity-30'
          )"
          aria-label="Previous image"
          @click="dir === 'rtl' ? handleNext() : handlePrevious()"
        >
          <SolarArrowRightBoldDuotone :class="cn('babylai:w-8 babylai:h-8', dir === 'rtl' ? '' : 'babylai:rotate-180')" />
        </Button>
        <Button
          variant="ghost"
          size="icon"
          :disabled="dir === 'rtl' ? currentIndex === 0 : currentIndex === imageUrls.length - 1"
          :class="cn(
            'babylai:absolute babylai:top-1/2 babylai:-translate-y-1/2 babylai:z-[60]',
            dir === 'rtl' ? 'babylai:left-4' : 'babylai:right-4',
            'babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-12 babylai:w-12 babylai:rounded-full babylai:disabled:opacity-30'
          )"
          aria-label="Next image"
          @click="dir === 'rtl' ? handlePrevious() : handleNext()"
        >
          <SolarArrowRightBoldDuotone :class="cn('babylai:w-8 babylai:h-8', dir === 'rtl' ? 'babylai:rotate-180' : '')" />
        </Button>
      </template>

      <!-- Zoom Controls -->
      <div
        :class="cn(
          'babylai:absolute babylai:bottom-4 babylai:z-[60] babylai:flex babylai:items-center babylai:gap-2',
          'babylai:bg-black/50 babylai:backdrop-blur-sm babylai:rounded-lg babylai:p-2',
          dir === 'rtl' ? 'babylai:right-1/2 babylai:translate-x-1/2' : 'babylai:left-1/2 babylai:-translate-x-1/2'
        )"
      >
        <Button variant="ghost" size="icon" :disabled="zoomLevel <= 0.5" class="babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9 babylai:disabled:opacity-30" aria-label="Zoom out" @click="handleZoomOut">
          <svg class="babylai:w-5 babylai:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7" /></svg>
        </Button>
        <span class="babylai:text-white babylai:text-sm babylai:font-medium babylai:min-w-12 babylai:text-center">{{ Math.round(zoomLevel * 100) }}%</span>
        <Button variant="ghost" size="icon" :disabled="zoomLevel >= 3" class="babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9 babylai:disabled:opacity-30" aria-label="Zoom in" @click="handleZoomIn">
          <svg class="babylai:w-5 babylai:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v6m3-3H7" /></svg>
        </Button>
        <Button v-if="zoomLevel !== 1" variant="ghost" size="sm" class="babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:px-3 babylai:ml-2" aria-label="Reset zoom" @click="handleResetZoom">Reset</Button>
        <div class="babylai:h-9 babylai:w-px babylai:bg-white/20 babylai:mx-1" />
        <Button variant="ghost" size="icon" class="babylai:text-white babylai:hover:text-white/80 babylai:hover:bg-white/10 babylai:h-9 babylai:w-9" aria-label="Download image" @click="handleDownload">
          <svg class="babylai:w-5 babylai:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
        </Button>
      </div>

      <!-- Image Counter -->
      <div
        v-if="hasMultipleImages"
        :class="cn(
          'babylai:absolute babylai:top-4 babylai:z-[60] babylai:bg-black/50 babylai:backdrop-blur-sm babylai:rounded-lg babylai:px-4 babylai:py-2',
          dir === 'rtl' ? 'babylai:right-1/2 babylai:translate-x-1/2' : 'babylai:left-1/2 babylai:-translate-x-1/2'
        )"
      >
        <span class="babylai:text-white babylai:text-sm babylai:font-medium">{{ currentIndex + 1 }} / {{ imageUrls.length }}</span>
      </div>

      <!-- Image Container -->
      <div
        class="babylai:flex babylai:items-center babylai:justify-center"
        :style="{
          transform: `translate(${imagePosition.x}px, ${imagePosition.y}px)`,
          cursor: zoomLevel > 1 ? (isDragging ? 'grabbing' : 'grab') : 'default',
        }"
      >
        <img
          :src="currentImageUrl"
          :alt="alt"
          class="babylai:max-w-[90vw] babylai:max-h-[85vh] babylai:object-contain babylai:select-none"
          :style="{ transform: `scale(${zoomLevel})`, transformOrigin: 'center center' }"
          draggable="false"
        />
      </div>
    </div>
  </div>
</template>
