import { useEffect, useRef, useState } from 'react'
import { imgUrl } from '../api'

const BASE_SHORTCUTS = [
  ['← / →', 'previous / next photo'],
  ['Space', 'next photo (Shift+Space back)'],
  ['?', 'show / hide shortcuts'],
  ['Esc', 'close'],
]

// `actions` defines the page's shortcuts as one table — display and dispatch
// come from the same entry, so the help overlay can't drift from behavior:
// { keys: ['p'], help: ['P', 'accept…'], run: (photo, key) => … }.
// Keys fire only outside text inputs and while the help overlay is closed.
export default function Lightbox({ photos, index, onClose, onNav, footer, actions }) {
  const photo = photos[index]
  const [showHelp, setShowHelp] = useState(false)

  // Handlers and view state live in a ref, updated every render, so the
  // window listener is attached once yet always dispatches against current
  // values — re-subscribing per render leaves a gap until effects re-run in
  // which a fast second keystroke hits a stale closure (and e.g. re-votes
  // the previous photo).
  const live = useRef({})
  live.current = { index, count: photos.length, photo, onClose, onNav, actions, showHelp }

  useEffect(() => {
    // Only text entry captures keys (Escape leaves the field); focus on a
    // checkbox or button must not disable lightbox navigation.
    const isTyping = (el) =>
      el.tagName === 'TEXTAREA' ||
      el.isContentEditable ||
      (el.tagName === 'INPUT' && !['checkbox', 'radio', 'button'].includes(el.type))
    const handler = (e) => {
      const s = live.current
      if (isTyping(e.target)) {
        if (e.key === 'Escape') e.target.blur()
        return
      }
      if (e.metaKey || e.ctrlKey || e.altKey) return
      if (e.key === 'Escape') {
        if (s.showHelp) setShowHelp(false)
        else s.onClose()
        return
      }
      if (e.key === '?') {
        setShowHelp((h) => !h)
        return
      }
      // With the help overlay up, keys must not act on the photo behind it.
      if (s.showHelp) return
      if (e.key === 'ArrowRight' || (e.key === ' ' && !e.shiftKey)) {
        e.preventDefault()
        if (s.index < s.count - 1) s.onNav(s.index + 1)
        return
      }
      if (e.key === 'ArrowLeft' || (e.key === ' ' && e.shiftKey)) {
        e.preventDefault()
        if (s.index > 0) s.onNav(s.index - 1)
        return
      }
      const key = e.key.toLowerCase()
      const action = s.actions?.find((a) => a.keys.includes(key))
      if (action && s.photo) action.run(s.photo, key)
    }
    window.addEventListener('keydown', handler)
    return () => window.removeEventListener('keydown', handler)
  }, [])

  useEffect(() => {
    document.body.style.overflow = 'hidden'
    return () => {
      document.body.style.overflow = ''
    }
  }, [])

  if (!photo) return null

  return (
    <div className="lightbox" onClick={onClose}>
      <div className="lb-top" onClick={(e) => e.stopPropagation()}>
        <span className="lb-name">{photo.filename}</span>
        <span className="lb-count">
          {index + 1} / {photos.length}
        </span>
        <button
          className="lb-btn"
          onClick={() => setShowHelp((h) => !h)}
          title="Keyboard shortcuts (?)"
        >
          ?
        </button>
        <button className="lb-btn" onClick={onClose} title="Close (Esc)">
          ✕
        </button>
      </div>
      <button
        className="lb-nav lb-prev"
        disabled={index === 0}
        onClick={(e) => {
          e.stopPropagation()
          onNav(index - 1)
        }}
      >
        ‹
      </button>
      <div className="lb-stage">
        <img
          className="lb-img"
          src={imgUrl(photo, 'preview')}
          alt={photo.filename}
          onClick={(e) => e.stopPropagation()}
        />
      </div>
      <button
        className="lb-nav lb-next"
        disabled={index === photos.length - 1}
        onClick={(e) => {
          e.stopPropagation()
          onNav(index + 1)
        }}
      >
        ›
      </button>
      {footer && (
        <div className="lb-footer" onClick={(e) => e.stopPropagation()}>
          {footer(photo)}
        </div>
      )}
      {showHelp && (
        <div
          className="lb-help"
          onClick={(e) => {
            e.stopPropagation()
            setShowHelp(false)
          }}
        >
          <div className="lb-help-card">
            <h3>Keyboard shortcuts</h3>
            {[...(actions?.map((a) => a.help) || []), ...BASE_SHORTCUTS].map(([keys, label]) => (
              <div key={keys} className="lb-help-row">
                <kbd>{keys}</kbd>
                <span className="muted">{label}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  )
}
