/**
 * @file
 * FlowDrop Plugin Selector Component JavaScript.
 *
 * Handles radio button selection and syncs with hidden input for form submission.
 *
 * @param {object} Drupal The Drupal API namespace.
 */

((Drupal) => {
  /**
   * Initialize a single plugin selector.
   *
   * @param {HTMLElement} selector
   *   The plugin selector container element.
   */
  function initializeSelector(selector) {
    // Find the target hidden input by ID from data attribute.
    const targetInputId = selector.getAttribute('data-flowdrop-target-input');
    const hiddenInput = targetInputId
      ? document.getElementById(targetInputId)
      : null;
    const radios = selector.querySelectorAll('[data-flowdrop-plugin-radio]');
    const cards = selector.querySelectorAll('.fd-plugin-selector__card');

    if (radios.length === 0) {
      return;
    }

    // Surface the full description as a native tooltip, but only when the
    // line clamp actually truncates it — so short descriptions don't get a
    // redundant tooltip.
    selector
      .querySelectorAll('.fd-plugin-selector__description')
      .forEach((desc) => {
        if (desc.scrollHeight > desc.clientHeight + 1) {
          desc.title = desc.textContent.trim();
        }
      });

    // Store handler references for cleanup.
    selector._flowdropRadioHandlers = [];
    selector._flowdropCardHandlers = [];

    // Handle radio button changes.
    radios.forEach((radio) => {
      const changeHandler = () => {
        if (radio.checked) {
          // Update hidden input value if it exists.
          if (hiddenInput) {
            hiddenInput.value = radio.value;
          }

          // Update card selected states.
          cards.forEach((card) => {
            const cardPluginId = card.getAttribute('data-plugin-id');
            if (cardPluginId === radio.value) {
              card.classList.add('fd-plugin-selector__card--selected');
            } else {
              card.classList.remove('fd-plugin-selector__card--selected');
            }
          });

          // Dispatch a custom event for any listeners.
          const event = new CustomEvent('flowdrop:plugin-selector:selected', {
            detail: {
              pluginId: radio.value,
              label: radio
                .closest('.fd-plugin-selector__card')
                ?.querySelector('.fd-plugin-selector__title')?.textContent,
            },
            bubbles: true,
          });
          selector.dispatchEvent(event);
        }
      };
      radio.addEventListener('change', changeHandler);
      selector._flowdropRadioHandlers.push({
        radio,
        handler: changeHandler,
      });
    });

    // Handle card clicks for better UX (click anywhere on card).
    cards.forEach((card) => {
      const clickHandler = (e) => {
        // Don't interfere if clicking directly on the radio.
        if (e.target.classList.contains('fd-plugin-selector__radio')) {
          return;
        }

        const radio = card.querySelector('.fd-plugin-selector__radio');
        if (radio && !radio.checked) {
          radio.checked = true;
          radio.dispatchEvent(new Event('change', { bubbles: true }));
        }
      };
      card.addEventListener('click', clickHandler);
      selector._flowdropCardHandlers.push({
        card,
        handler: clickHandler,
      });
    });

    // Collapsible provider groups (collapsed by default).
    const groups = selector.querySelectorAll('[data-flowdrop-plugin-group]');
    const noResults = selector.querySelector(
      '[data-flowdrop-plugin-no-results]',
    );

    const setGroupExpanded = (group, expanded) => {
      const toggle = group.querySelector('[data-flowdrop-plugin-group-toggle]');
      const content = group.querySelector('.fd-plugin-selector__group-content');
      if (!toggle || !content) {
        return;
      }
      toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
      content.hidden = !expanded;
    };

    selector._flowdropGroupHandlers = [];
    groups.forEach((group) => {
      const toggle = group.querySelector('[data-flowdrop-plugin-group-toggle]');
      if (!toggle) {
        return;
      }
      const toggleHandler = () => {
        const expanded = toggle.getAttribute('aria-expanded') === 'true';
        setGroupExpanded(group, !expanded);
      };
      toggle.addEventListener('click', toggleHandler);
      selector._flowdropGroupHandlers.push({ toggle, handler: toggleHandler });
    });

    // Expandable "in use" usage summaries (sit outside the card click area).
    const usageToggles = selector.querySelectorAll(
      '[data-flowdrop-plugin-usage-toggle]',
    );
    selector._flowdropUsageHandlers = [];
    usageToggles.forEach((toggle) => {
      const list = document.getElementById(
        toggle.getAttribute('aria-controls'),
      );
      if (!list) {
        return;
      }
      const usageHandler = () => {
        const expanded = toggle.getAttribute('aria-expanded') === 'true';
        toggle.setAttribute('aria-expanded', expanded ? 'false' : 'true');
        list.hidden = expanded;
      };
      toggle.addEventListener('click', usageHandler);
      selector._flowdropUsageHandlers.push({ toggle, handler: usageHandler });
    });

    // Live client-side search filtering.
    const searchInput = selector.querySelector('[data-flowdrop-plugin-search]');
    if (searchInput) {
      const applySearch = () => {
        const term = searchInput.value.trim().toLowerCase();
        let anyMatch = false;

        groups.forEach((group) => {
          const items = group.querySelectorAll('.fd-plugin-selector__item');
          let matches = 0;

          items.forEach((item) => {
            const text = item.getAttribute('data-search-text') || '';
            const isMatch = term === '' || text.includes(term);
            item.hidden = !isMatch;
            if (isMatch) {
              matches += 1;
            }
          });

          if (term === '') {
            // Restore default: visible and expanded.
            group.hidden = false;
            setGroupExpanded(group, true);
          } else {
            group.hidden = matches === 0;
            setGroupExpanded(group, matches > 0);
          }

          if (matches > 0) {
            anyMatch = true;
          }
        });

        if (noResults) {
          noResults.hidden = !(term !== '' && !anyMatch);
        }
      };

      const inputHandler = () => applySearch();
      // Prevent Enter in the search field from submitting the form.
      const keyHandler = (e) => {
        if (e.key === 'Enter') {
          e.preventDefault();
        }
      };
      searchInput.addEventListener('input', inputHandler);
      searchInput.addEventListener('keydown', keyHandler);
      selector._flowdropSearchHandlers = [
        { type: 'input', handler: inputHandler },
        { type: 'keydown', handler: keyHandler },
      ];
      selector._flowdropSearchInput = searchInput;
    }

    // Handle keyboard navigation.
    const keydownHandler = (e) => {
      if (
        e.key === 'ArrowDown' ||
        e.key === 'ArrowUp' ||
        e.key === 'ArrowLeft' ||
        e.key === 'ArrowRight'
      ) {
        const focusedCard = document.activeElement?.closest(
          '.fd-plugin-selector__card',
        );
        if (!focusedCard) {
          return;
        }

        const allCards = Array.from(cards);
        const currentIndex = allCards.indexOf(focusedCard);

        let nextIndex;
        if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
          nextIndex = currentIndex + 1;
          if (nextIndex >= allCards.length) {
            nextIndex = 0;
          }
        } else {
          nextIndex = currentIndex - 1;
          if (nextIndex < 0) {
            nextIndex = allCards.length - 1;
          }
        }

        const nextCard = allCards[nextIndex];
        const nextRadio = nextCard?.querySelector('.fd-plugin-selector__radio');
        if (nextRadio) {
          nextRadio.focus();
          nextRadio.checked = true;
          nextRadio.dispatchEvent(new Event('change', { bubbles: true }));
          e.preventDefault();
        }
      }
    };
    selector.addEventListener('keydown', keydownHandler);
    selector._flowdropKeydownHandler = keydownHandler;
  }

  /**
   * Initialize plugin selector components.
   *
   * @type {object}
   */
  Drupal.behaviors.flowdropPluginSelector = {
    attach(context) {
      // Find all plugin selector containers.
      const selectors = context.querySelectorAll(
        '[data-flowdrop-plugin-selector]:not([data-flowdrop-initialized])',
      );

      selectors.forEach((selector) => {
        initializeSelector(selector);
        selector.setAttribute('data-flowdrop-initialized', 'true');
      });
    },

    detach(context, settings, trigger) {
      if (trigger !== 'unload') {
        return;
      }

      const selectors = context.querySelectorAll(
        '[data-flowdrop-plugin-selector][data-flowdrop-initialized]',
      );

      selectors.forEach((selector) => {
        // Remove radio change handlers
        if (selector._flowdropRadioHandlers) {
          selector._flowdropRadioHandlers.forEach((entry) => {
            entry.radio.removeEventListener('change', entry.handler);
          });
          selector._flowdropRadioHandlers = null;
        }

        // Remove card click handlers
        if (selector._flowdropCardHandlers) {
          selector._flowdropCardHandlers.forEach((entry) => {
            entry.card.removeEventListener('click', entry.handler);
          });
          selector._flowdropCardHandlers = null;
        }

        // Remove keydown handler
        if (selector._flowdropKeydownHandler) {
          selector.removeEventListener(
            'keydown',
            selector._flowdropKeydownHandler,
          );
          selector._flowdropKeydownHandler = null;
        }

        // Remove group toggle handlers
        if (selector._flowdropGroupHandlers) {
          selector._flowdropGroupHandlers.forEach((entry) => {
            entry.toggle.removeEventListener('click', entry.handler);
          });
          selector._flowdropGroupHandlers = null;
        }

        // Remove usage toggle handlers
        if (selector._flowdropUsageHandlers) {
          selector._flowdropUsageHandlers.forEach((entry) => {
            entry.toggle.removeEventListener('click', entry.handler);
          });
          selector._flowdropUsageHandlers = null;
        }

        // Remove search handlers
        if (selector._flowdropSearchHandlers && selector._flowdropSearchInput) {
          selector._flowdropSearchHandlers.forEach((entry) => {
            selector._flowdropSearchInput.removeEventListener(
              entry.type,
              entry.handler,
            );
          });
          selector._flowdropSearchHandlers = null;
          selector._flowdropSearchInput = null;
        }

        selector.removeAttribute('data-flowdrop-initialized');
      });
    },
  };
})(Drupal);
