'use client';

import Image from 'next/image';
import * as React from 'react';
import type { PropertyMedia } from '@/lib/listings-api';
import { cn } from '@/lib/utils';

// ─── Types ──────────────────────────────────────────────

interface ImageLightboxProps {
  images: PropertyMedia[];
  initialIndex?: number;
  open: boolean;
  onClose: () => void;
}

// ─── Swipe hook ─────────────────────────────────────────

function useSwipe(onSwipeLeft: () => void, onSwipeRight: () => void) {
  const touchStart = React.useRef<{ x: number; y: number } | null>(null);
  const touchEnd = React.useRef<{ x: number; y: number } | null>(null);
  const minSwipeDistance = 50;

  const onTouchStart = React.useCallback((e: React.TouchEvent) => {
    const touch = e.targetTouches[0];
    if (!touch) return;
    touchEnd.current = null;
    touchStart.current = { x: touch.clientX, y: touch.clientY };
  }, []);

  const onTouchMove = React.useCallback((e: React.TouchEvent) => {
    const touch = e.targetTouches[0];
    if (!touch) return;
    touchEnd.current = { x: touch.clientX, y: touch.clientY };
  }, []);

  const onTouchEnd = React.useCallback(() => {
    if (!touchStart.current || !touchEnd.current) return;
    const distanceX = touchStart.current.x - touchEnd.current.x;
    const distanceY = Math.abs(touchStart.current.y - touchEnd.current.y);
    // Only consider horizontal swipes (ignore vertical scrolling)
    if (Math.abs(distanceX) > minSwipeDistance && Math.abs(distanceX) > distanceY) {
      if (distanceX > 0) {
        onSwipeLeft();
      } else {
        onSwipeRight();
      }
    }
  }, [onSwipeLeft, onSwipeRight]);

  return { onTouchStart, onTouchMove, onTouchEnd };
}

// ─── Focus trap hook ────────────────────────────────────

function useFocusTrap(containerRef: React.RefObject<HTMLDivElement | null>, active: boolean) {
  React.useEffect(() => {
    if (!active) return;
    const container = containerRef.current;
    if (!container) return;

    const previouslyFocused = document.activeElement as HTMLElement | null;
    const focusableSelector =
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';

    // Focus the first focusable element
    const firstFocusable = container.querySelector<HTMLElement>(focusableSelector);
    firstFocusable?.focus();

    function handleKeyDown(e: KeyboardEvent) {
      if (e.key !== 'Tab' || !container) return;

      const focusableElements = container.querySelectorAll<HTMLElement>(focusableSelector);
      if (focusableElements.length === 0) return;

      const first = focusableElements[0] as HTMLElement | undefined;
      const last = focusableElements[focusableElements.length - 1] as HTMLElement | undefined;
      if (!first || !last) return;

      if (e.shiftKey) {
        if (document.activeElement === first) {
          e.preventDefault();
          last.focus();
        }
      } else {
        if (document.activeElement === last) {
          e.preventDefault();
          first.focus();
        }
      }
    }

    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      previouslyFocused?.focus();
    };
  }, [containerRef, active]);
}

// ─── Component ──────────────────────────────────────────

export function ImageLightbox({ images, initialIndex = 0, open, onClose }: ImageLightboxProps) {
  const [currentIndex, setCurrentIndex] = React.useState(initialIndex);
  const [isImageLoaded, setIsImageLoaded] = React.useState(false);
  const containerRef = React.useRef<HTMLDivElement>(null);
  const thumbnailsRef = React.useRef<HTMLDivElement>(null);

  // Reset index when lightbox opens with a new initialIndex
  React.useEffect(() => {
    if (open) {
      setCurrentIndex(initialIndex);
      setIsImageLoaded(false);
    }
  }, [open, initialIndex]);

  // Lock body scroll
  React.useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = '';
    }
    return () => {
      document.body.style.overflow = '';
    };
  }, [open]);

  // Focus trap
  useFocusTrap(containerRef, open);

  // Navigation handlers
  const goToPrevious = React.useCallback(() => {
    setCurrentIndex((i) => (i > 0 ? i - 1 : images.length - 1));
    setIsImageLoaded(false);
  }, [images.length]);

  const goToNext = React.useCallback(() => {
    setCurrentIndex((i) => (i < images.length - 1 ? i + 1 : 0));
    setIsImageLoaded(false);
  }, [images.length]);

  // Keyboard navigation
  React.useEffect(() => {
    if (!open) return;

    function handleKeyDown(e: KeyboardEvent) {
      switch (e.key) {
        case 'Escape':
          onClose();
          break;
        case 'ArrowLeft':
          goToPrevious();
          break;
        case 'ArrowRight':
          goToNext();
          break;
      }
    }

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [open, onClose, goToPrevious, goToNext]);

  // Swipe support
  const swipeHandlers = useSwipe(goToNext, goToPrevious);

  // Scroll active thumbnail into view
  React.useEffect(() => {
    if (!open || !thumbnailsRef.current) return;
    const activeThumb = thumbnailsRef.current.children[currentIndex] as HTMLElement | undefined;
    activeThumb?.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
  }, [currentIndex, open]);

  // Preload adjacent images
  React.useEffect(() => {
    if (!open || images.length <= 1) return;
    const preloadIndices = [
      (currentIndex + 1) % images.length,
      (currentIndex - 1 + images.length) % images.length,
    ];
    preloadIndices.forEach((idx) => {
      const imageToPreload = images[idx];
      if (!imageToPreload) return;
      const img = new window.Image();
      img.src = imageToPreload.url;
    });
  }, [currentIndex, open, images]);

  if (!open || images.length === 0) return null;

  const currentImage = images[currentIndex];
  if (!currentImage) return null;

  return (
    <div
      ref={containerRef}
      className="fixed inset-0 z-50 flex flex-col bg-black/95"
      role="dialog"
      aria-modal="true"
      aria-label="Xem ảnh toàn màn hình"
    >
      {/* Top bar */}
      <div className="flex items-center justify-between px-4 py-3">
        <p className="text-sm text-white/80">
          {currentIndex + 1} / {images.length}
        </p>
        {currentImage.caption && (
          <p className="mx-4 flex-1 truncate text-center text-sm text-white/70">
            {currentImage.caption}
          </p>
        )}
        <button
          onClick={onClose}
          className="rounded-full p-2 text-white/80 transition-colors hover:bg-white/10 hover:text-white"
          aria-label="Đóng (Escape)"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M18 6 6 18" />
            <path d="m6 6 12 12" />
          </svg>
        </button>
      </div>

      {/* Main image area */}
      <div
        className="relative flex flex-1 items-center justify-center px-12 md:px-20"
        {...swipeHandlers}
      >
        {/* Loading spinner */}
        {!isImageLoaded && (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="h-8 w-8 animate-spin rounded-full border-2 border-white/20 border-t-white/80" />
          </div>
        )}

        {/* Image */}
        <div className="relative h-full w-full">
          <Image
            key={currentImage.id}
            src={currentImage.url}
            alt={currentImage.caption || `Ảnh ${currentIndex + 1}`}
            fill
            sizes="100vw"
            className={cn(
              'object-contain transition-opacity duration-200',
              isImageLoaded ? 'opacity-100' : 'opacity-0',
            )}
            priority
            onLoad={() => setIsImageLoaded(true)}
          />
        </div>

        {/* Navigation arrows */}
        {images.length > 1 && (
          <>
            <button
              onClick={goToPrevious}
              className="absolute left-2 top-1/2 -translate-y-1/2 rounded-full bg-white/10 p-3 text-white transition-colors hover:bg-white/25 md:left-4"
              aria-label="Ảnh trước (phím mũi tên trái)"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="m15 18-6-6 6-6" />
              </svg>
            </button>
            <button
              onClick={goToNext}
              className="absolute right-2 top-1/2 -translate-y-1/2 rounded-full bg-white/10 p-3 text-white transition-colors hover:bg-white/25 md:right-4"
              aria-label="Ảnh tiếp (phím mũi tên phải)"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </button>
          </>
        )}
      </div>

      {/* Thumbnail strip */}
      {images.length > 1 && (
        <div className="border-t border-white/10 px-4 py-3">
          <div
            ref={thumbnailsRef}
            className="flex justify-center gap-2 overflow-x-auto"
            role="tablist"
            aria-label="Danh sách ảnh thu nhỏ"
          >
            {images.map((img, index) => (
              <button
                key={img.id}
                role="tab"
                aria-selected={index === currentIndex}
                aria-label={img.caption || `Ảnh ${index + 1}`}
                onClick={() => {
                  setCurrentIndex(index);
                  setIsImageLoaded(false);
                }}
                className={cn(
                  'relative h-14 w-14 flex-shrink-0 overflow-hidden rounded-md border-2 transition-all md:h-16 md:w-16',
                  index === currentIndex
                    ? 'border-white ring-1 ring-white/50'
                    : 'border-transparent opacity-50 hover:opacity-80',
                )}
              >
                <Image
                  src={img.url}
                  alt={img.caption || `Thumbnail ${index + 1}`}
                  fill
                  sizes="64px"
                  className="object-cover"
                />
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
