import { useEffect, useRef, useState } from 'react'
import { NavLink, useLocation } from 'react-router-dom'

// One dropdown section in the public header — a menu an admin created from
// Admin → Navigation (THEMING_AND_NAV.md §7, Phase 10).
//
// It **opens on click, never on hover**. Hover menus are unusable on touch, and
// the alternative (make the trigger a link too) means tapping to open navigates
// away instead. A section is a container, not a destination, so the trigger has
// no `to` at all.
//
// Everything else here is the keyboard and dismissal contract a menu needs:
// Escape closes and returns focus to the trigger, an outside press closes,
// navigating closes, and Arrow Up/Down walk the items. `aria-haspopup` +
// `aria-expanded` are what let a screen reader announce it as a menu rather than
// as a button that mysteriously changes the page.
export default function NavDropdown({ label, items, linkStyle }) {
  const [open, setOpen] = useState(false)
  const wrapRef = useRef(null)
  const triggerRef = useRef(null)
  const location = useLocation()

  // The trigger shows the active treatment when the page you are on lives in
  // this menu — otherwise entering a section makes the header look like nothing
  // is selected.
  const holdsActive = items.some((i) => (i.end ? location.pathname === i.to : location.pathname.startsWith(i.to)))

  // Close on navigation. The menu is rendered inside a sticky header that
  // survives route changes, so nothing else would dismiss it.
  useEffect(() => setOpen(false), [location.pathname])

  useEffect(() => {
    if (!open) return undefined
    const onKey = (e) => {
      if (e.key !== 'Escape') return
      setOpen(false)
      triggerRef.current?.focus()
    }
    // `mousedown`, not `click`: closing on the press means a press that lands on
    // another trigger opens that one in the same gesture.
    const onOutside = (e) => {
      if (!wrapRef.current?.contains(e.target)) setOpen(false)
    }
    document.addEventListener('keydown', onKey)
    document.addEventListener('mousedown', onOutside)
    return () => {
      document.removeEventListener('keydown', onKey)
      document.removeEventListener('mousedown', onOutside)
    }
  }, [open])

  // Roving focus with the arrow keys, wrapping at both ends.
  const onMenuKeyDown = (e) => {
    if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') return
    e.preventDefault()
    const links = [...(wrapRef.current?.querySelectorAll('[data-menu-item]') || [])]
    if (links.length === 0) return
    const at = links.indexOf(document.activeElement)
    const next = e.key === 'ArrowDown' ? (at + 1) % links.length : (at - 1 + links.length) % links.length
    links[at === -1 ? 0 : next].focus()
  }

  return (
    <div ref={wrapRef} style={{ position: 'relative' }} onKeyDown={onMenuKeyDown}>
      <button
        ref={triggerRef}
        type="button"
        className="pill"
        aria-haspopup="true"
        aria-expanded={open}
        onClick={() => setOpen((v) => !v)}
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          gap: 6,
          ...(holdsActive || open
            ? { background: 'var(--accent)', color: 'var(--bg-deep)', borderColor: 'var(--accent)' }
            : {}),
        }}
      >
        {label}
        <svg
          width="10"
          height="10"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="3"
          strokeLinecap="round"
          strokeLinejoin="round"
          aria-hidden="true"
          focusable="false"
          style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }}
        >
          <path d="M6 9l6 6 6-6" />
        </svg>
      </button>

      {open && (
        <div
          role="menu"
          aria-label={label}
          style={{
            position: 'absolute',
            top: 'calc(100% + 6px)',
            left: 0,
            minWidth: 190,
            // The header wraps, so a menu near the right edge must not push the
            // page sideways on a narrow screen.
            maxWidth: 'calc(100vw - 24px)',
            display: 'flex',
            flexDirection: 'column',
            gap: 2,
            padding: 6,
            borderRadius: 'var(--radius-card)',
            border: '1px solid var(--line)',
            background: 'var(--panel-flat)',
            boxShadow: 'var(--shadow-card)',
            zIndex: 40,
          }}
        >
          {items.map((item) => (
            <NavLink
              key={item.kind === 'link' ? item.id : item.to}
              to={item.to}
              end={item.end}
              role="menuitem"
              data-menu-item=""
              onClick={() => setOpen(false)}
              className="sans"
              style={({ isActive }) => ({
                padding: '7px 10px',
                borderRadius: 'var(--radius-input)',
                fontSize: '0.85rem',
                textDecoration: 'none',
                whiteSpace: 'nowrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                ...linkStyle({ isActive }),
                ...(isActive ? {} : { color: 'var(--muted)' }),
              })}
            >
              {item.label}
            </NavLink>
          ))}
        </div>
      )}
    </div>
  )
}
