/**
 * Dropdown: custom select. Toggle panel, select option, keyboard nav, ARIA.
 * Structure: .dropdown[data-dropdown], .dropdown__trigger, input[type=hidden],
 * .dropdown__panel, .dropdown__option[data-value].
 *
 * Initialization: automatic. Any .dropdown[data-dropdown] in the DOM is
 * initialized on load (or on DOMContentLoaded if the script runs before DOM ready).
 */
(function () {
  function init() {
    document.querySelectorAll('.dropdown[data-dropdown]').forEach((root) => {
      const trigger = root.querySelector('.dropdown__trigger');
      const panel = root.querySelector('.dropdown__panel');
      const options = panel ? panel.querySelectorAll('.dropdown__option') : [];
      const hiddenInput = root.querySelector('input[type="hidden"]');
      if (!trigger || !panel || options.length === 0) return;

      const panelId = panel.id || 'dropdown-panel-' + Math.random().toString(36).slice(2);
      panel.id = panelId;
      trigger.setAttribute('aria-haspopup', 'listbox');
      trigger.setAttribute('aria-expanded', 'false');
      trigger.setAttribute('aria-controls', panelId);
      panel.setAttribute('role', 'listbox');

      options.forEach((opt, i) => {
        opt.id = opt.id || `dropdown-opt-${panelId}-${i}`;
        opt.setAttribute('role', 'option');
      });

      function getValue() {
        return hiddenInput?.value ?? '';
      }

      function findOptionByValue(value) {
        return Array.from(options).find((opt) => opt.getAttribute('data-value') === value) ?? null;
      }

      function setValue(value, label) {
        if (hiddenInput) hiddenInput.value = value;
        trigger.textContent = label ?? findOptionByValue(value)?.textContent.trim() ?? '';
        options.forEach((opt) => {
          opt.setAttribute('aria-selected', opt.getAttribute('data-value') === value ? 'true' : 'false');
        });
      }

      function open() {
        panel.hidden = false;
        trigger.setAttribute('aria-expanded', 'true');
        const current = findOptionByValue(getValue());
        const idx = current ? Array.prototype.indexOf.call(options, current) : 0;
        setActiveIndex(idx);
      }

      function close() {
        panel.hidden = true;
        trigger.setAttribute('aria-expanded', 'false');
        trigger.removeAttribute('aria-activedescendant');
      }

      function setActiveIndex(idx) {
        idx = Math.max(0, Math.min(idx, options.length - 1));
        const opt = options[idx];
        trigger.setAttribute('aria-activedescendant', opt.id);
        opt.focus();
      }

      function selectOption(opt) {
        setValue(opt.getAttribute('data-value'), opt.textContent.trim());
        close();
      }

      trigger.addEventListener('click', () => (panel.hidden ? open() : close()));

      trigger.addEventListener('keydown', (e) => {
        if (e.key === 'ArrowDown') {
          e.preventDefault();
          panel.hidden ? open() : setActiveIndex(0);
        } else if (e.key === 'ArrowUp') {
          e.preventDefault();
          panel.hidden ? open() : setActiveIndex(options.length - 1);
        } else if (e.key === 'Escape') {
          e.preventDefault();
          close();
          trigger.focus();
        }
      });

      options.forEach((opt, idx) => {
        opt.addEventListener('click', () => selectOption(opt));
        opt.addEventListener('keydown', (e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            selectOption(opt);
          } else if (e.key === 'ArrowDown') {
            e.preventDefault();
            setActiveIndex(idx + 1);
          } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            setActiveIndex(idx - 1);
          } else if (e.key === 'Escape') {
            e.preventDefault();
            close();
            trigger.focus();
          }
        });
      });

      document.addEventListener('click', (e) => {
        if (!root.contains(e.target)) close();
      });

      const initialValue = getValue();
      const initialOpt = findOptionByValue(initialValue);
      if (initialOpt) trigger.textContent = initialOpt.textContent.trim();
      options.forEach((opt) => {
        opt.setAttribute('aria-selected', opt.getAttribute('data-value') === initialValue ? 'true' : 'false');
      });
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
