// Image lightbox — a single, shared, animated modal for viewing gallery images
// large. Mounted once (see app.jsx) and driven imperatively from anywhere via
// window.openImageLightbox(images, index): the separately-transpiled page files
// just call that global. Handles real images (img.src) and the striped
// placeholders identically, so it works before any real photography is dropped
// in. Keyboard (←/→/Esc), prev/next, swipe, and backdrop-tap all close/navigate.
//
// Animation: the backdrop fades + blurs in; the figure scales up from 0.92 and
// rises a few px on a soft ease. Closing reverses it, then unmounts after the
// transition. Respects prefers-reduced-motion (snaps, no transform).

function Lightbox() {
  const [state, setState] = React.useState(null);   // { images, index } | null
  const [shown, setShown] = React.useState(false);   // drives the enter/leave transition
  const closeTimer = React.useRef(0);
  const touch = React.useRef(null);
  const mobile = window.useIsMobile ? window.useIsMobile() : false;
  const reduce = typeof window.matchMedia === 'function'
    && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  // Register the global opener.
  React.useEffect(() => {
    window.openImageLightbox = (images, index = 0) => {
      if (!images || !images.length) return;
      clearTimeout(closeTimer.current);
      setState({ images, index });
      // Flip to shown on the next frame so the entrance transition runs.
      setTimeout(() => setShown(true), 20);
    };
    return () => { try { delete window.openImageLightbox; } catch (e) {} };
  }, []);

  const close = React.useCallback(() => {
    setShown(false);
    clearTimeout(closeTimer.current);
    closeTimer.current = setTimeout(() => setState(null), reduce ? 0 : 320);
  }, [reduce]);

  const go = React.useCallback((dir) => {
    setState((s) => (s ? { ...s, index: (s.index + dir + s.images.length) % s.images.length } : s));
  }, []);

  // Keyboard + body scroll lock while open.
  React.useEffect(() => {
    if (!state) return;
    const onKey = (e) => {
      if (e.key === 'Escape') close();
      else if (e.key === 'ArrowRight') go(1);
      else if (e.key === 'ArrowLeft') go(-1);
    };
    window.addEventListener('keydown', onKey);
    const prevOverflow = document.documentElement.style.overflow;
    document.documentElement.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.documentElement.style.overflow = prevOverflow;
    };
  }, [state, close, go]);

  if (!state) return null;
  const { images, index } = state;
  const img = images[index] || {};
  const multi = images.length > 1;
  const ease = 'cubic-bezier(.16,1,.3,1)';

  const onTouchStart = (e) => { touch.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (touch.current == null) return;
    const dx = e.changedTouches[0].clientX - touch.current;
    touch.current = null;
    if (multi && Math.abs(dx) > 44) go(dx < 0 ? 1 : -1);
  };

  const navBtn = (dir, glyph, side) => (
    <button onClick={(e) => { e.stopPropagation(); go(dir); }} aria-label={dir < 0 ? 'Previous' : 'Next'}
      style={{
        position: 'absolute', top: '50%', [side]: 'clamp(8px, 3vw, 28px)', transform: 'translateY(-50%)',
        width: 46, height: 46, borderRadius: '50%', cursor: 'pointer',
        border: '1px solid rgba(255,255,255,0.28)', background: 'rgba(255,255,255,0.08)',
        color: 'var(--paper)', fontSize: 20, lineHeight: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
        backdropFilter: 'blur(6px)', WebkitBackdropFilter: 'blur(6px)', transition: 'background .15s, border-color .15s',
      }}
      onMouseEnter={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.18)'; e.currentTarget.style.borderColor = 'rgba(255,255,255,0.5)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; e.currentTarget.style.borderColor = 'rgba(255,255,255,0.28)'; }}>
      {glyph}
    </button>
  );

  return (
    <div
      onClick={close}
      style={{
        position: 'fixed', inset: 0, zIndex: 9000,
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        padding: mobile ? '14px' : 'clamp(16px, 5vw, 56px)', boxSizing: 'border-box',
        background: 'oklch(20% 0.02 140 / 0.78)',
        backdropFilter: shown ? 'blur(8px)' : 'blur(0px)', WebkitBackdropFilter: shown ? 'blur(8px)' : 'blur(0px)',
        opacity: shown ? 1 : 0,
        transition: reduce ? 'none' : `opacity .3s ease, backdrop-filter .3s ease`,
      }}>

      {/* close */}
      <button onClick={(e) => { e.stopPropagation(); close(); }} aria-label="Close"
        style={{
          position: 'absolute', top: 'clamp(12px, 3vw, 24px)', right: 'clamp(12px, 3vw, 24px)',
          width: 42, height: 42, borderRadius: '50%', cursor: 'pointer', zIndex: 2,
          border: '1px solid rgba(255,255,255,0.28)', background: 'rgba(255,255,255,0.08)',
          color: 'var(--paper)', fontSize: 17, display: 'flex', alignItems: 'center', justifyContent: 'center',
          backdropFilter: 'blur(6px)', WebkitBackdropFilter: 'blur(6px)', transition: 'background .15s, border-color .15s',
        }}
        onMouseEnter={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.18)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; }}>✕</button>

      {/* figure */}
      <figure
        onClick={(e) => e.stopPropagation()}
        onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}
        style={{
          margin: 0, maxWidth: mobile ? '100%' : 'min(960px, 100%)', width: mobile ? '100%' : 'auto',
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16,
          opacity: shown ? 1 : 0,
          transform: reduce ? 'none' : (shown ? 'scale(1) translateY(0)' : 'scale(.92) translateY(10px)'),
          transition: reduce ? 'none' : `opacity .32s ease, transform .38s ${ease}`,
        }}>
        <div style={{
          position: 'relative', maxWidth: '100%',
          width: (img.src || img.video) ? (mobile ? '100%' : 'auto') : (mobile ? '100%' : 'min(680px, 100%)'),
          aspectRatio: (img.src || img.video) ? 'auto' : '4 / 3',
        }}>
          {img.video ? (
            <video key={index} src={img.video} poster={img.src || undefined}
              autoPlay loop muted playsInline controls
              style={{ display: 'block', width: mobile ? '100%' : 'auto', maxWidth: '100%',
                maxHeight: mobile ? '80vh' : '74vh', objectFit: 'contain', background: '#000',
                border: '1px solid rgba(255,255,255,0.14)' }} />
          ) : img.src ? (
            <img key={index} src={img.src} alt={img.title || ''}
              style={{ display: 'block', width: mobile ? '100%' : 'auto', maxWidth: '100%',
                maxHeight: mobile ? '80vh' : '74vh', objectFit: 'contain',
                border: '1px solid rgba(255,255,255,0.14)' }} />
          ) : (
            <div style={{
              width: '100%', height: '100%', boxSizing: 'border-box',
              backgroundColor: 'var(--paper)',
              backgroundImage: 'repeating-linear-gradient(135deg, transparent 0 12px, var(--paper-2) 12px 14px)',
              border: '1px solid var(--rule)', display: 'flex', alignItems: 'flex-end',
            }}>
              <div className="mono" style={{ fontSize: 12, color: 'var(--ink-3)', padding: '12px 14px',
                letterSpacing: 0.4, textTransform: 'uppercase' }}>[{img.tag}]</div>
            </div>
          )}
        </div>

        {/* caption */}
        <figcaption style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10,
          color: 'var(--paper)', textAlign: 'center' }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'center', gap: 12, flexWrap: 'wrap' }}>
            {img.title && <span style={{ fontSize: 14 }}>{img.title}</span>}
            {multi && <span className="mono tnum" style={{ fontSize: 12, color: 'rgba(255,255,255,0.55)' }}>
              {String(index + 1).padStart(2, '0')} / {String(images.length).padStart(2, '0')}
            </span>}
          </div>
          {/* mobile: swipe dots (arrows are desktop-only) */}
          {multi && mobile && (
            <div style={{ display: 'flex', gap: 7, alignItems: 'center' }}>
              {images.map((_, i) => (
                <span key={i} style={{ width: i === index ? 18 : 6, height: 6, borderRadius: 3,
                  background: i === index ? 'var(--paper)' : 'rgba(255,255,255,0.3)', transition: 'all .25s ease' }} />
              ))}
            </div>
          )}
        </figcaption>
      </figure>

      {multi && !mobile && navBtn(-1, '‹', 'left')}
      {multi && !mobile && navBtn(1, '›', 'right')}
    </div>
  );
}

window.Lightbox = Lightbox;
