import { useEffect, useId, useRef } from 'react'
import { X } from 'lucide-react'

const SIZES = {
  sm: 'max-w-md',
  md: 'max-w-lg',
  lg: 'max-w-3xl',
  xl: 'max-w-4xl',
}

const FOCUSABLE = [
  'a[href]',
  'button:not([disabled])',
  'input:not([disabled])',
  'select:not([disabled])',
  'textarea:not([disabled])',
  '[tabindex]:not([tabindex="-1"])',
].join(', ')

/**
 * Modale de base : fermeture par Échap et clic sur le fond, piège à focus,
 * restitution du focus à la fermeture, verrouillage du défilement, sémantique
 * ARIA. Tous les modals de l'application passent par ici.
 */
export default function Modal({
  title,
  subtitle,
  icon,
  size = 'md',
  onClose,
  headerRight,
  footer,
  children,
  bodyClassName = 'overflow-y-auto p-4',
  panelClassName = '',
}) {
  const panelRef   = useRef(null)
  const onCloseRef = useRef(onClose)
  const titleId    = useId()

  // `onClose` est souvent une lambda recréée à chaque rendu du parent : on la
  // lit via une ref pour que l'effet ne se rejoue pas (sinon le focus sauterait
  // au premier champ à chaque rafraîchissement automatique).
  useEffect(() => { onCloseRef.current = onClose })

  useEffect(() => {
    const previouslyFocused = document.activeElement
    const panel = panelRef.current
    const firstFocusable = panel?.querySelector(FOCUSABLE)
    ;(firstFocusable ?? panel)?.focus({ preventScroll: true })

    const onKeyDown = (e) => {
      if (e.key === 'Escape') {
        e.stopPropagation()
        onCloseRef.current?.()
        return
      }
      if (e.key !== 'Tab' || !panel) return

      const items = [...panel.querySelectorAll(FOCUSABLE)].filter(el => el.offsetParent !== null)
      if (items.length === 0) return
      const first = items[0]
      const last  = items[items.length - 1]

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

    document.addEventListener('keydown', onKeyDown)
    const previousOverflow = document.body.style.overflow
    document.body.style.overflow = 'hidden'

    return () => {
      document.removeEventListener('keydown', onKeyDown)
      document.body.style.overflow = previousOverflow
      previouslyFocused?.focus?.({ preventScroll: true })
    }
  }, [])

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm animate-fade-in"
      onMouseDown={(e) => { if (e.target === e.currentTarget) onClose() }}
    >
      <div
        ref={panelRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby={titleId}
        tabIndex={-1}
        className={`w-full ${SIZES[size] ?? SIZES.md} flex flex-col max-h-[88vh] bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl outline-none animate-modal-in ${panelClassName}`}
      >
        <div className="flex items-center justify-between gap-3 px-4 py-3 border-b border-gray-800 flex-shrink-0">
          <div className="flex items-center gap-2.5 min-w-0">
            {icon}
            <div className="min-w-0">
              <h2 id={titleId} className="font-semibold text-sm truncate">{title}</h2>
              {subtitle && <p className="text-xs text-gray-500 truncate mt-0.5">{subtitle}</p>}
            </div>
          </div>
          <div className="flex items-center gap-2 flex-shrink-0">
            {headerRight}
            <button
              onClick={onClose}
              aria-label="Fermer"
              className="p-1.5 rounded-lg hover:bg-gray-800 text-gray-500 hover:text-gray-200 transition-colors"
            >
              <X size={16} />
            </button>
          </div>
        </div>

        {/* `min-h-0` autorise l'enfant à défiler dans un conteneur flex */}
        <div className={`flex-1 min-h-0 ${bodyClassName}`}>
          {children}
        </div>

        {footer && (
          <div className="px-4 py-3 border-t border-gray-800 flex-shrink-0">
            {footer}
          </div>
        )}
      </div>
    </div>
  )
}
