/**
 * Non-side-effect class export for `<step-progress-ui>`.
 *
 * 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/step-progress`
 * (which imports this file + calls `defineIfFree()`).
 *
 * @see ../../USAGE.md#registration--auto-vs-explicit
 */

/**
 * <step-progress-ui value="3" total="10" caption="Step 3 of 10"></step-progress-ui>
 * <step-progress-ui value="3" total="10"></step-progress-ui>            <!-- no caption -->
 * <step-progress-ui value="10" total="10" caption="All steps complete"></step-progress-ui>
 *
 * Discrete-dash step progress indicator. One dash per step in the
 * total; the first `value` dashes carry [data-active] and paint with
 * --a-accent. Used in registration + onboarding flows; replaces the
 * bespoke `[data-onb-progress]` / `[data-reg-progress]` markup.
 *
 * Primitive shape (per ROADMAP § Done):
 *   `<step-progress-ui value="N" total="M" caption="...">`
 *
 * Caption is optional; pass via attribute. Free-form text passes
 * straight through; `<text-ui>` styling can be replicated with
 * default-slot HTML if needed (the auto-mint uses plain text).
 */

import { UIElement } from '../../core/element.js';
import { logicalSlotted } from '../../core/logical-children.js';

export class UIStepProgress extends UIElement {
  static properties = {
    value:   { type: Number, default: 0,  reflect: true },
    total:   { type: Number, default: 0,  reflect: true },
    caption: { type: String, default: '', reflect: true },
  };

  static template = () => null;

  #captionEl = null;
  #trackEl = null;

  connected() {
    this.setAttribute('role', 'progressbar');
    this.setAttribute('aria-valuemin', '0');

    // Auto-mint internal structure if the consumer didn't provide custom slots.
    if (!logicalSlotted(this, 'caption').length && !logicalSlotted(this, 'track').length) {
      this.#captionEl = document.createElement('span');
      this.#captionEl.setAttribute('slot', 'caption');
      this.appendChild(this.#captionEl);

      this.#trackEl = document.createElement('div');
      this.#trackEl.setAttribute('slot', 'track');
      this.appendChild(this.#trackEl);
    } else {
      this.#captionEl = logicalSlotted(this, 'caption')[0];
      this.#trackEl = logicalSlotted(this, 'track')[0];
    }
  }

  render() {
    const total = Math.max(0, this.total | 0);
    const clamped = Math.max(0, Math.min(total, this.value | 0));

    this.setAttribute('aria-valuemax', String(total));
    this.setAttribute('aria-valuenow', String(clamped));

    // Caption — text content if attribute set; cleared otherwise.
    // Skip if the consumer passed in a custom caption slot (preserve their content).
    if (this.#captionEl && !this.#captionEl.dataset.custom) {
      this.#captionEl.textContent = this.caption || '';
      this.#captionEl.toggleAttribute('hidden', !this.caption);
    }

    // Track — sync span count with `total`; mark first `value` as active.
    if (this.#trackEl) {
      const existing = this.#trackEl.children.length;
      while (this.#trackEl.children.length < total) {
        this.#trackEl.appendChild(document.createElement('span'));
      }
      while (this.#trackEl.children.length > total) {
        this.#trackEl.lastElementChild.remove();
      }
      for (let i = 0; i < this.#trackEl.children.length; i++) {
        this.#trackEl.children[i].toggleAttribute('data-active', i < clamped);
      }
    }
  }

  disconnected() {
    this.#captionEl = null;
    this.#trackEl = null;
  }
}
