'use client';

import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';
import { createPortal } from 'react-dom';

const noopSubscribe = () => () => {};

export interface LightboxItem {
  src: string;
  alt: string;
}

interface LightboxProps {
  items: LightboxItem[];
  index: number | null;
  onChange: (index: number) => void;
  onClose: () => void;
}

/** Shared image viewer (port of the original main.js lightbox): arrows, Esc, swipe, backdrop click. */
export default function Lightbox({ items, index, onChange, onClose }: LightboxProps) {
  const closeRef = useRef<HTMLButtonElement>(null);
  const lastFocused = useRef<Element | null>(null);
  const startX = useRef<number | null>(null);
  const isClient = useSyncExternalStore(noopSubscribe, () => true, () => false);
  const open = index !== null && items.length > 0;
  const current = open ? ((index % items.length) + items.length) % items.length : 0;

  const step = useCallback((delta: number) => onChange((current + delta + items.length) % items.length), [current, items.length, onChange]);

  useEffect(() => {
    if (!open) return;
    lastFocused.current = document.activeElement;
    document.body.classList.add('lightbox-open');
    closeRef.current?.focus();
    return () => {
      document.body.classList.remove('lightbox-open');
      (lastFocused.current as HTMLElement | null)?.focus?.();
    };
  }, [open]);

  useEffect(() => {
    if (!open) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowLeft') step(-1);
      if (e.key === 'ArrowRight') step(1);
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open, onClose, step]);

  if (!isClient) return null;

  const item = open ? items[current] : undefined;
  const multiple = items.length > 1;

  return createPortal(
    <div
      className={`lightbox${open ? ' open' : ''}`}
      id="lightbox"
      role="dialog"
      aria-modal="true"
      aria-label="Image viewer"
      aria-hidden={!open}
      onClick={(e) => e.target === e.currentTarget && onClose()}
      onTouchStart={(e) => (startX.current = e.changedTouches[0].clientX)}
      onTouchEnd={(e) => {
        if (startX.current === null) return;
        const delta = e.changedTouches[0].clientX - startX.current;
        if (Math.abs(delta) > 50) step(delta > 0 ? -1 : 1);
        startX.current = null;
      }}
    >
      <button type="button" className="lightbox-btn lightbox-close" aria-label="Close" ref={closeRef} onClick={onClose}>
        <svg className="iconSize-24" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
        </svg>
      </button>
      <button type="button" className="lightbox-btn lightbox-prev" aria-label="Previous image" style={multiple ? undefined : { display: 'none' }} onClick={() => step(-1)}>
        <svg className="iconSize-24" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M15 6L9 12L15 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>
      <button type="button" className="lightbox-btn lightbox-next" aria-label="Next image" style={multiple ? undefined : { display: 'none' }} onClick={() => step(1)}>
        <svg className="iconSize-24" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path d="M9 6L15 12L9 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>
      <figure className="lightbox-figure m-0">
        {item && <img className="lightbox-img" src={item.src} alt={item.alt} />}
        <figcaption className="lightbox-caption text-sm">{item?.alt}</figcaption>
      </figure>
      <span className="lightbox-count text-sm">{open ? `${current + 1} / ${items.length}` : ''}</span>
    </div>,
    document.body,
  );
}
