import { useEffect, type ReactNode, type KeyboardEvent, type MouseEvent } from 'react'

interface ModalProps {
  open: boolean
  title: ReactNode
  onClose: () => void
  width?: number
  footer?: ReactNode
  children: ReactNode
  closeLabel?: string
}

export function Modal({ open, title, onClose, width = 420, footer, children, closeLabel = 'Close' }: ModalProps) {
  useEffect(() => {
    if (!open) return
    const onKey = (e: globalThis.KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault()
        onClose()
      }
    }
    document.addEventListener('keydown', onKey)
    // Lock body scroll while the modal is open.
    const prev = document.body.style.overflow
    document.body.style.overflow = 'hidden'
    return () => {
      document.removeEventListener('keydown', onKey)
      document.body.style.overflow = prev
    }
  }, [open, onClose])

  if (!open) return null

  const onBackdropClick = (e: MouseEvent<HTMLDivElement>) => {
    if (e.target === e.currentTarget) onClose()
  }
  const onPanelKey = (e: KeyboardEvent<HTMLDivElement>) => {
    // Stop Escape from bubbling to other key handlers in the page; the
    // document listener above already handles closing.
    if (e.key === 'Escape') e.stopPropagation()
  }

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-label={typeof title === 'string' ? title : undefined}
      onClick={onBackdropClick}
      style={{
        position: 'fixed', inset: 0, zIndex: 100,
        background: 'rgba(0, 0, 0, 0.6)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}
    >
      <div
        className="bracket panel"
        onKeyDown={onPanelKey}
        style={{ width, padding: 20 }}
      >
        <span className="br" />
        <div className="flex items-center justify-between mb-3">
          <span className="sect-head">{title}</span>
          <button type="button" onClick={onClose} className="ibtn" aria-label={closeLabel} title={closeLabel}>
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
              <line x1="18" y1="6" x2="6" y2="18" />
              <line x1="6" y1="6" x2="18" y2="18" />
            </svg>
          </button>
        </div>

        <div className="space-y-3">{children}</div>

        {footer && (
          <div
            className="mt-5 pt-4 flex items-center justify-end gap-2"
            style={{ borderTop: '1px dashed var(--border-hair)' }}
          >
            {footer}
          </div>
        )}
      </div>
    </div>
  )
}
