/**
 * Non-side-effect class export for `<toggle-option-ui>` (+ co-located primitives).
 *
 * Importing this file gives you the class(es) without auto-registering the tag.
 * Useful for test isolation, subclassing with tag-name override, or selective
 * composition.
 *
 * The auto-register path stays at `@adia-ai/web-components/components/toggle-group`
 * (which imports this file + calls `defineIfFree()`).
 *
 * @see ../../USAGE.md#registration--auto-vs-explicit
 */

/**
 * <toggle-group-ui value="bold,italic">
 *   <toggle-option-ui value="bold" icon="text-b"></toggle-option-ui>
 *   <toggle-option-ui value="italic" icon="text-italic"></toggle-option-ui>
 *   <toggle-option-ui value="underline" icon="text-underline"></toggle-option-ui>
 * </toggle-group-ui>
 *
 * Multi-select button group (unlike segmented which is single-select).
 *
 * Properties:
 *   value  — comma-separated selected values
 *   single — restrict to one active option at a time (default false: multi-select)
 */

import { UIElement } from '../../core/element.js';

// ── Toggle Option ──
//
// Parent-managed. Selection state flows through `toggle-group-ui`'s `value`
// (and `single` mode flag). Items don't expose `checked` — parent applies
// `data-selected` on the DOM element when the item's `value` is part of the
// group's comma-separated `value` list. Consistent with native `<option>`
// inside `<select>`.

export class UIToggleOption extends UIElement {
  static properties = {
    value:    { type: String,  default: '', reflect: true },
    text:     { type: String,  default: '', reflect: true },
    icon:     { type: String,  default: '', reflect: true },
    disabled: { type: Boolean, default: false, reflect: true },
  };

  static template = () => null;

  #stamped = false;

  connected() {
    this.setAttribute('role', 'button');
    this.setAttribute('tabindex', '0');
  }

  render() {
    if (!this.#stamped) {
      this.#stamped = true;
      this.#stamp();
    }
    if (this.disabled) this.setAttribute('aria-disabled', 'true');
    else this.removeAttribute('aria-disabled');
  }

  #stamp() {
    let inner = '';
    if (this.icon) inner += `<icon-ui name="${this.icon}"></icon-ui>`;
    if (this.text) inner += `<span data-text>${this.text}</span>`;
    this.innerHTML = inner;
  }

  disconnected() {
    this.#stamped = false;
  }
}

export class UIToggleGroup extends UIElement {
  static properties = {
    value:  { type: String,  default: '',    reflect: true },
    single: { type: Boolean, default: false, reflect: true },
  };

  static template = () => null;

  #bound = false;

  get #valueSet() {
    return new Set(this.value ? this.value.split(',').map(v => v.trim()).filter(Boolean) : []);
  }

  connected() {
    if (!this.#bound) {
      this.#bound = true;
      this.addEventListener('click', this.#onClick);
      this.addEventListener('keydown', this.#onKey);
    }
    this.setAttribute('role', 'group');
  }

  render() {
    const selected = this.#valueSet;
    for (const opt of this.querySelectorAll('toggle-option-ui')) {
      const optVal = opt.value || opt.getAttribute('value') || '';
      if (selected.has(optVal)) {
        opt.setAttribute('data-selected', '');
        opt.setAttribute('aria-pressed', 'true');
      } else {
        opt.removeAttribute('data-selected');
        opt.setAttribute('aria-pressed', 'false');
      }
    }
  }

  #toggle(opt) {
    if (opt.disabled) return;
    const optVal = opt.value || opt.getAttribute('value') || '';
    if (!optVal) return;

    const selected = this.#valueSet;

    if (this.single) {
      if (selected.has(optVal)) {
        selected.clear();
      } else {
        selected.clear();
        selected.add(optVal);
      }
    } else {
      if (selected.has(optVal)) selected.delete(optVal);
      else selected.add(optVal);
    }

    this.value = [...selected].join(',');
    this.dispatchEvent(new CustomEvent('change', { bubbles: true, detail: { value: this.value } }));
  }

  #onClick = (e) => {
    const opt = e.target.closest('toggle-option-ui');
    if (opt && this.contains(opt)) this.#toggle(opt);
  };

  #onKey = (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      const opt = e.target.closest('toggle-option-ui');
      if (opt && this.contains(opt)) this.#toggle(opt);
    }
  };

  disconnected() {
    this.removeEventListener('click', this.#onClick);
    this.removeEventListener('keydown', this.#onKey);
    this.#bound = false;
  }
}
