// Copyright 2026 Moko Consulting. All rights reserved.
// SPDX-License-Identifier: MIT

import {fomanticQuery} from '../modules/fomantic/base.ts';
import {addDelegatedEventListener, queryElemChildren, queryElems, toggleElem} from '../utils/dom.ts';

/**
 * Generic multiselect combo list component.
 * Works with the "shared/combolist" template to provide a reusable
 * dropdown with search, checkable items, and a selected-items display list.
 *
 * Usage: add class="combo-multiselect" to the container element.
 * The component is self-contained — no backend calls, just updates the hidden input.
 */
class ComboMultiselect {
  container: HTMLElement;
  elDropdown: HTMLElement;
  elList: HTMLElement;
  elComboValue: HTMLInputElement;

  constructor(container: HTMLElement) {
    this.container = container;
    this.elDropdown = container.querySelector<HTMLElement>(':scope > .ui.dropdown')!;
    this.elList = container.querySelector<HTMLElement>(':scope > .combo-multiselect-list')!;
    this.elComboValue = container.querySelector<HTMLInputElement>(':scope > .combo-value')!;
  }

  collectCheckedValues(): string[] {
    return Array.from(
      this.elDropdown.querySelectorAll('.menu > .item.checked'),
      (el) => el.getAttribute('data-value')!,
    );
  }

  updateUiList() {
    const checkedValues = this.collectCheckedValues();
    const elEmptyTip = this.elList.querySelector(':scope > .item.empty-list')!;
    queryElemChildren(this.elList, '.item:not(.empty-list)', (el) => el.remove());

    for (const value of checkedValues) {
      const el = this.elDropdown.querySelector<HTMLElement>(`.menu > .item[data-value="${CSS.escape(value)}"]`);
      if (!el) continue;
      const labelText = el.querySelector('.item-label')?.textContent || value;
      const listItem = document.createElement('span');
      listItem.classList.add('item');
      listItem.textContent = labelText;
      this.elList.append(listItem);
    }

    toggleElem(elEmptyTip, checkedValues.length === 0);
    this.elComboValue.value = checkedValues.join(',');
    this.elComboValue.dispatchEvent(new Event('change', {bubbles: true}));
  }

  onItemClick(elItem: HTMLElement, e: Event) {
    e.preventDefault();

    if (elItem.matches('.clear-selection')) {
      queryElems(this.elDropdown, '.menu > .item', (el) => el.classList.remove('checked'));
      this.updateUiList();
      return;
    }

    elItem.classList.toggle('checked');
    this.updateUiList();
  }

  init() {
    // Restore checked state from initial value
    const initialValues = this.elComboValue.value ? this.elComboValue.value.split(',') : [];
    for (const value of initialValues) {
      const elItem = this.elDropdown.querySelector<HTMLElement>(`.menu > .item[data-value="${CSS.escape(value)}"]`);
      elItem?.classList.add('checked');
    }
    this.updateUiList();

    addDelegatedEventListener(this.elDropdown, 'click', '.item', (el, e) => this.onItemClick(el, e));

    fomanticQuery(this.elDropdown).dropdown('setting', {
      action: 'nothing',
      fullTextSearch: 'exact',
      hideDividers: 'empty',
    });
  }
}

export function initComboMultiselect() {
  queryElems(document, '.combo-multiselect', (el) => {
    if (el.hasAttribute('data-combo-inited')) return;
    el.setAttribute('data-combo-inited', 'true');
    new ComboMultiselect(el).init();
  });
}
