/**
 * Dynamic domain select for the security-check create wizard.
 *
 * Listens to the core [data-app-lookup] customer picker and loads the customer's
 * domains from the Security BC gateway. Falls back to manual entry when the
 * customer has no domains.
 */
import { getJson } from '/js/core/app-http.js';
import { resolveHost } from '/js/core/app-dom.js';

const SELECTOR = '#security-domain-group[data-app-component="security-customer-domain-select"]';
const EMPTY_API = Object.freeze({ destroy: () => {} });

const resolveGroup = (root) => {
  const host = resolveHost(root);
  if (host instanceof HTMLElement && host.matches(SELECTOR)) {
    return host;
  }
  return host.querySelector(SELECTOR);
};

export function initSecurityCustomerDomainSelect(root = document) {
  const group = resolveGroup(root);
  if (!group) {
    return EMPTY_API;
  }

  const scope = group.closest('form') || document;
  const lookupContainer = scope.querySelector('[data-app-lookup]');
  const domainSelect = group.querySelector('#security-domain');
  const domainNoInput = group.querySelector('#security-domain-no');
  const domainUrlInput = group.querySelector('#security-domain-url');
  const feedback = group.querySelector('#security-domain-feedback');
  const manualBlock = group.querySelector('#security-domain-manual');
  const manualNoInput = group.querySelector('#security-domain-manual-no');
  const manualUrlInput = group.querySelector('#security-domain-manual-url');
  if (!lookupContainer || !domainSelect) {
    return EMPTY_API;
  }

  const domainsUrl = group.dataset.domainsUrl || '';
  const textInitial = group.dataset.textInitial || '';
  const textLoading = group.dataset.textLoading || '';
  const textSelect = group.dataset.textSelect || '';
  const textError = group.dataset.textError || '';

  const listenerController = new AbortController();
  const requestController = new AbortController();
  const on = (target, type, handler, options = {}) => {
    if (!target || typeof target.addEventListener !== 'function') {
      return;
    }
    target.addEventListener(type, handler, { ...options, signal: listenerController.signal });
  };

  const clearOptions = () => {
    while (domainSelect.options.length > 0) {
      domainSelect.remove(0);
    }
  };

  const addPlaceholder = (text) => {
    const opt = document.createElement('option');
    opt.value = '';
    opt.textContent = text;
    domainSelect.appendChild(opt);
  };

  const setFeedback = (text, variant) => {
    if (!feedback) {
      return;
    }
    feedback.textContent = text;
    feedback.hidden = !text;
    feedback.dataset.variant = variant || '';
  };

  const showManual = (show) => {
    if (!manualBlock) {
      return;
    }
    manualBlock.hidden = !show;
    domainSelect.closest('.app-wizard-domain-select-wrap')?.toggleAttribute('hidden', show);
    if (!show && manualNoInput) manualNoInput.value = '';
    if (!show && manualUrlInput) manualUrlInput.value = '';
    if (show) {
      if (domainNoInput) domainNoInput.value = '';
      if (domainUrlInput) domainUrlInput.value = '';
    }
  };

  const resetDomain = () => {
    clearOptions();
    addPlaceholder(textInitial);
    domainSelect.disabled = true;
    if (domainNoInput) domainNoInput.value = '';
    if (domainUrlInput) domainUrlInput.value = '';
    setFeedback('', '');
    showManual(false);
  };

  const loadDomains = async (debitorNo) => {
    clearOptions();
    addPlaceholder(textLoading);
    domainSelect.disabled = true;
    group.setAttribute('aria-busy', 'true');
    setFeedback('', '');

    try {
      const data = await getJson(`${domainsUrl}?debitor_no=${encodeURIComponent(debitorNo)}`, {
        signal: requestController.signal,
      });
      const items = Array.isArray(data) ? data : [];

      clearOptions();
      addPlaceholder(textSelect);

      if (items.length === 0) {
        domainSelect.disabled = true;
        showManual(true);
        return;
      }
      showManual(false);

      items.forEach((item) => {
        const opt = document.createElement('option');
        opt.value = item.value || '';
        opt.textContent = item.label || item.value || '';
        opt.dataset.url = item.url || '';
        domainSelect.appendChild(opt);
      });
      domainSelect.disabled = false;
    } catch (error) {
      if (!(error instanceof Error && error.name === 'AbortError')) {
        clearOptions();
        addPlaceholder(textSelect);
        domainSelect.disabled = true;
        setFeedback(textError, 'error');
      }
    } finally {
      group.removeAttribute('aria-busy');
    }
  };

  on(domainSelect, 'change', () => {
    const selected = domainSelect.options[domainSelect.selectedIndex];
    if (domainNoInput) domainNoInput.value = selected?.value || '';
    if (domainUrlInput) domainUrlInput.value = selected?.dataset.url || '';
  });

  if (manualNoInput) {
    on(manualNoInput, 'input', () => {
      if (domainNoInput) domainNoInput.value = manualNoInput.value.trim();
    });
  }
  if (manualUrlInput) {
    on(manualUrlInput, 'input', () => {
      if (domainUrlInput) domainUrlInput.value = manualUrlInput.value.trim();
    });
  }

  on(lookupContainer, 'lookup:select', (event) => {
    const debitorNo = event.detail?.value || '';
    if (debitorNo) {
      void loadDomains(debitorNo);
    } else {
      resetDomain();
    }
  });

  on(lookupContainer, 'lookup:clear', () => {
    resetDomain();
  });

  const initialDebitor = group.dataset.initialDebitor || '';
  const initialDomain = group.dataset.initialDomain || '';
  if (initialDebitor) {
    void loadDomains(initialDebitor).then(() => {
      if (initialDomain && !domainSelect.disabled) {
        domainSelect.value = initialDomain;
        domainSelect.dispatchEvent(new Event('change'));
      }
    });
  } else if (domainNoInput && domainNoInput.value && manualNoInput) {
    manualNoInput.value = domainNoInput.value;
  }

  return {
    destroy: () => {
      listenerController.abort();
      requestController.abort();
    },
  };
}
