import { ref, computed, watch, onBeforeUnmount } from 'vue'

export interface LightboxImage {
  src: string
  alt?: string
}

export interface UseImageLightboxOptions {
  /**
   * Whether to enable keyboard navigation (arrow keys, escape)
   */
  enableKeyboardNavigation?: boolean

  /**
   * Whether to close lightbox when clicking backdrop
   */
  closeOnBackdropClick?: boolean

  /**
   * Whether to enable swipe gestures on touch devices
   */
  enableSwipeGestures?: boolean
}

export function useImageLightbox(
  images: LightboxImage[],
  options: UseImageLightboxOptions = {}
) {
  const {
    enableKeyboardNavigation = true,
    closeOnBackdropClick = true,
    enableSwipeGestures = true
  } = options

  // Core reactive state
  const isOpen = ref(false)
  const currentIndex = ref(0)

  // Computed properties
  const currentImage = computed(() => {
    if (!images.length || currentIndex.value < 0) return null
    return images[Math.min(currentIndex.value, images.length - 1)]
  })

  const hasPrevious = computed(() => images.length > 1)
  const hasNext = computed(() => images.length > 1)
  const totalImages = computed(() => images.length)

  // Navigation methods
  const open = (index: number = 0) => {
    if (images.length === 0) return

    currentIndex.value = Math.max(0, Math.min(index, images.length - 1))
    isOpen.value = true

    // Prevent body scroll when lightbox is open
    document.body.style.overflow = 'hidden'
  }

  const close = () => {
    isOpen.value = false

    // Restore body scroll
    document.body.style.overflow = ''
  }

  const goToPrevious = () => {
    if (!hasPrevious.value) return

    currentIndex.value = currentIndex.value > 0
      ? currentIndex.value - 1
      : images.length - 1
  }

  const goToNext = () => {
    if (!hasNext.value) return

    currentIndex.value = currentIndex.value < images.length - 1
      ? currentIndex.value + 1
      : 0
  }

  const goToIndex = (index: number) => {
    if (index < 0 || index >= images.length) return
    currentIndex.value = index
  }

  // Keyboard navigation
  const handleKeydown = (event: KeyboardEvent) => {
    if (!isOpen.value || !enableKeyboardNavigation) return

    switch (event.key) {
      case 'Escape':
        event.preventDefault()
        close()
        break
      case 'ArrowLeft':
        event.preventDefault()
        goToPrevious()
        break
      case 'ArrowRight':
        event.preventDefault()
        goToNext()
        break
      case ' ': // Spacebar
        event.preventDefault()
        goToNext()
        break
    }
  }

  // Touch/swipe gesture handling
  let touchStartX = 0
  let touchStartY = 0
  const swipeThreshold = 50

  const handleTouchStart = (event: TouchEvent) => {
    if (!enableSwipeGestures || !isOpen.value) return

    touchStartX = event.touches[0].clientX
    touchStartY = event.touches[0].clientY
  }

  const handleTouchEnd = (event: TouchEvent) => {
    if (!enableSwipeGestures || !isOpen.value) return

    const touchEndX = event.changedTouches[0].clientX
    const touchEndY = event.changedTouches[0].clientY

    const deltaX = touchEndX - touchStartX
    const deltaY = touchEndY - touchStartY

    // Only process horizontal swipes (ignore mostly vertical swipes)
    if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > swipeThreshold) {
      if (deltaX > 0) {
        goToPrevious()
      } else {
        goToNext()
      }
    }
  }


  // Setup event listeners
  watch(isOpen, (newIsOpen) => {
    if (newIsOpen) {
      document.addEventListener('keydown', handleKeydown)
      document.addEventListener('touchstart', handleTouchStart, { passive: true })
      document.addEventListener('touchend', handleTouchEnd, { passive: true })
    } else {
      document.removeEventListener('keydown', handleKeydown)
      document.removeEventListener('touchstart', handleTouchStart)
      document.removeEventListener('touchend', handleTouchEnd)
    }
  })

  // Cleanup on unmount
  onBeforeUnmount(() => {
    close()
    document.removeEventListener('keydown', handleKeydown)
    document.removeEventListener('touchstart', handleTouchStart)
    document.removeEventListener('touchend', handleTouchEnd)
  })

  return {
    // State
    isOpen: readonly(isOpen),
    currentIndex: readonly(currentIndex),
    currentImage,

    // Computed
    hasPrevious,
    hasNext,
    totalImages,

    // Methods
    open,
    close,
    goToPrevious,
    goToNext,
    goToIndex
  }
}

// Helper to create readonly refs
function readonly<T>(ref: import('vue').Ref<T>) {
  return computed(() => ref.value)
}