import { defineTrait } from '../define.js';

const FOCUSABLE_SELECTOR = 'a[href], [role="button"][tabindex], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable]';

export const focusTrap = defineTrait({
  name: 'focus-trap',
  category: 'keyboard-navigation',
  description: 'Traps Tab/Shift+Tab within a container',
  attributes: ['data-focus-trap-active'],
  events: ['focus-trap-escape'],
  config: [],
  setup({ host }) {
    function getFocusableElements() {
      return [...host.querySelectorAll(FOCUSABLE_SELECTOR)].filter(
        (el) => !el.hasAttribute('disabled') && el.offsetParent !== null,
      );
    }

    function onKeyDown(e) {
      if (e.key === 'Escape') {
        host.dispatchEvent(new CustomEvent('focus-trap-escape', { bubbles: true }));
        return;
      }

      if (e.key !== 'Tab') return;

      const focusable = getFocusableElements();
      if (focusable.length === 0) {
        e.preventDefault();
        return;
      }

      const first = focusable[0];
      const last = focusable[focusable.length - 1];

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

    host.setAttribute('data-focus-trap-active', '');
    host.addEventListener('keydown', onKeyDown);

    // Auto-focus first focusable element
    requestAnimationFrame(() => {
      const focusable = getFocusableElements();
      if (focusable.length > 0) {
        focusable[0].focus();
      }
    });

    return () => {
      host.removeEventListener('keydown', onKeyDown);
      host.removeAttribute('data-focus-trap-active');
    };
  },
});
