import { useEffect, useRef } from 'react'

// useFocusTrap makes a slide-over / modal keyboard-accessible. Attach the
// returned ref to the dialog container and, while it's mounted, it:
//   • moves focus into the panel on open (so Tab/Escape work without a click),
//   • keeps Tab/Shift+Tab cycling within the panel instead of escaping to the
//     page behind the backdrop, and
//   • restores focus to whatever was focused before it opened on unmount.
// Escape handling stays with each panel, which has its own close semantics.
export function useFocusTrap<T extends HTMLElement>() {
  const ref = useRef<T>(null)

  useEffect(() => {
    const node = ref.current
    if (!node) return

    // Remember where focus was so we can hand it back when the panel closes.
    const previouslyFocused = document.activeElement as HTMLElement | null

    const focusables = () =>
      Array.from(
        node.querySelectorAll<HTMLElement>(
          'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])',
        ),
      ).filter((el) => el.offsetParent !== null)

    // Focus the first interactive element, or the container itself as a fallback.
    const first = focusables()[0]
    if (first) first.focus()
    else node.focus()

    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key !== 'Tab') return
      const items = focusables()
      if (items.length === 0) {
        e.preventDefault()
        return
      }
      const firstEl = items[0]
      const lastEl = items[items.length - 1]
      const active = document.activeElement
      if (e.shiftKey && active === firstEl) {
        e.preventDefault()
        lastEl.focus()
      } else if (!e.shiftKey && active === lastEl) {
        e.preventDefault()
        firstEl.focus()
      }
    }

    node.addEventListener('keydown', onKeyDown)
    return () => {
      node.removeEventListener('keydown', onKeyDown)
      previouslyFocused?.focus?.()
    }
  }, [])

  return ref
}
