'use client';

import { useEffect, useCallback, useRef, useState } from 'react';
import {
  XMarkIcon,
  ChevronLeftIcon,
  ChevronRightIcon,
  ArrowDownTrayIcon,
} from '@heroicons/react/24/outline';
import Spinner from '@/components/ui/Spinner';

export interface LightboxItem {
  id: string;
  previewUrl: string;
  downloadUrl: string;
  filename?: string;
  /** Small thumbnail for the filmstrip; falls back to previewUrl. */
  thumbUrl?: string;
}

interface LightboxProps {
  items: LightboxItem[];
  index: number;
  onClose: () => void;
  onNavigate: (index: number) => void;
  /** Extra per-item action buttons rendered in the top bar (admin use). */
  renderActions?: (item: LightboxItem, index: number) => React.ReactNode;
  /**
   * Handles the download in JS instead of navigating, so the button can show
   * progress. Without it the button stays a plain <a download>.
   */
  onDownload?: (item: LightboxItem) => void;
  /** Id of the item currently downloading (pairs with onDownload). */
  downloadingId?: string | null;
  downloadLabels?: { download: string; downloading: string };
}

/**
 * Full-screen photo lightbox with keyboard and swipe navigation, in the
 * style of the admin gallery preview modal (fixed inset-0 bg-black/90).
 */
export default function Lightbox({
  items,
  index,
  onClose,
  onNavigate,
  renderActions,
  onDownload,
  downloadingId,
  downloadLabels,
}: LightboxProps) {
  const touchStart = useRef<{ x: number; y: number } | null>(null);
  const activeThumbRef = useRef<HTMLButtonElement | null>(null);
  const item = items[index];
  const hasMultiple = items.length > 1;
  const downloading = !!downloadingId && item?.id === downloadingId;

  const prev = useCallback(() => {
    onNavigate(index > 0 ? index - 1 : items.length - 1);
  }, [index, items.length, onNavigate]);
  const next = useCallback(() => {
    onNavigate(index < items.length - 1 ? index + 1 : 0);
  }, [index, items.length, onNavigate]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowLeft') prev();
      if (e.key === 'ArrowRight') next();
    };
    window.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [onClose, prev, next]);

  // Keep the active thumbnail centred in the filmstrip as you navigate.
  useEffect(() => {
    activeThumbRef.current?.scrollIntoView({
      behavior: 'smooth',
      inline: 'center',
      block: 'nearest',
    });
  }, [index]);

  if (!item) return null;

  return (
    <div
      className="fixed inset-0 bg-black/90 z-50 flex flex-col"
      onClick={onClose}
      onTouchStart={(e) => {
        touchStart.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
      }}
      onTouchEnd={(e) => {
        if (touchStart.current === null) return;
        const dx = e.changedTouches[0].clientX - touchStart.current.x;
        const dy = e.changedTouches[0].clientY - touchStart.current.y;
        touchStart.current = null;
        // Only treat as a swipe when it's clearly horizontal.
        if (Math.abs(dx) < 50 || Math.abs(dx) < Math.abs(dy)) return;
        if (dx > 0) prev();
        else next();
      }}
    >
      <button
        className="absolute top-4 right-4 text-white hover:text-gray-300 z-10 p-2 -m-2"
        onClick={onClose}
        aria-label="Close"
      >
        <XMarkIcon className="w-8 h-8" />
      </button>

      <div
        className="absolute top-4 left-4 z-10 flex items-center gap-4"
        onClick={(e) => e.stopPropagation()}
      >
        {onDownload ? (
          <button
            type="button"
            onClick={() => onDownload(item)}
            disabled={downloading}
            aria-busy={downloading}
            aria-label={
              downloading
                ? downloadLabels?.downloading || 'Downloading…'
                : downloadLabels?.download || 'Download'
            }
            className={`text-white hover:text-gray-300 flex items-center ${
              downloading ? 'cursor-wait' : ''
            }`}
          >
            {downloading ? (
              <Spinner className="w-6 h-6" />
            ) : (
              <ArrowDownTrayIcon className="w-7 h-7" />
            )}
          </button>
        ) : (
          <a
            href={item.downloadUrl}
            download={item.filename || true}
            className="text-white hover:text-gray-300"
            aria-label="Download"
          >
            <ArrowDownTrayIcon className="w-7 h-7" />
          </a>
        )}
        {renderActions?.(item, index)}
      </div>

      {/* Main image area */}
      <div className="relative flex-1 min-h-0 flex items-center justify-center">
        {hasMultiple && (
          <>
            <button
              className="absolute left-2 md:left-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white z-10 p-2"
              onClick={(e) => {
                e.stopPropagation();
                prev();
              }}
              aria-label="Previous"
            >
              <ChevronLeftIcon className="w-9 h-9" />
            </button>
            <button
              className="absolute right-2 md:right-4 top-1/2 -translate-y-1/2 text-white/80 hover:text-white z-10 p-2"
              onClick={(e) => {
                e.stopPropagation();
                next();
              }}
              aria-label="Next"
            >
              <ChevronRightIcon className="w-9 h-9" />
            </button>
          </>
        )}

        {/* eslint-disable-next-line @next/next/no-img-element */}
        {/* Nothing is layered over the image (the navigation buttons sit at
            the edges), and neither -webkit-touch-callout nor -webkit-user-
            select is suppressed here, so iOS long-press → "Save to Photos"
            still works as a backup to the save sheet. Don't add select-none. */}
        <img
          src={item.previewUrl}
          alt=""
          className="max-w-[95vw] max-h-full object-contain [-webkit-touch-callout:default]"
          onClick={(e) => e.stopPropagation()}
          draggable={false}
        />
      </div>

      {/* Counter + thumbnail filmstrip you can skip through. */}
      <div
        className="shrink-0 pb-3 pt-2"
        onClick={(e) => e.stopPropagation()}
        onTouchStart={(e) => e.stopPropagation()}
        onTouchEnd={(e) => e.stopPropagation()}
      >
        <div className="text-center text-white/70 text-sm mb-2">
          {index + 1} / {items.length}
        </div>
        {hasMultiple && (
          <div className="flex gap-2 overflow-x-auto px-4 pb-1 justify-start sm:justify-center [scrollbar-width:thin]">
            {items.map((it, i) => (
              <button
                key={it.id}
                ref={i === index ? activeThumbRef : null}
                onClick={() => onNavigate(i)}
                aria-label={`Photo ${i + 1}`}
                aria-current={i === index}
                className={`relative shrink-0 overflow-hidden rounded transition ${
                  i === index
                    ? 'ring-2 ring-white opacity-100'
                    : 'opacity-50 hover:opacity-90'
                }`}
              >
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src={it.thumbUrl || it.previewUrl}
                  alt=""
                  className="h-14 w-14 sm:h-16 sm:w-16 object-cover"
                  draggable={false}
                />
              </button>
            ))}
          </div>
        )}
      </div>

      {/* Preload neighbours so prev/next feels instant. */}
      <div className="hidden" aria-hidden>
        {hasMultiple && (
          <>
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={items[(index + 1) % items.length].previewUrl} alt="" />
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={items[(index - 1 + items.length) % items.length].previewUrl} alt="" />
          </>
        )}
      </div>
    </div>
  );
}
