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

/**
 * <timeline-ui> — Vertical (or horizontal) event / progress log.
 *
 * Each <timeline-item-ui> is one entry, with its own state via the `status`
 * enum (idle | active | completed | error), optional icon, duration, and an
 * expandable outcomes list. `[spinner]` is an orthogonal presentation hint
 * that animates the dot as a ring when combined with `status="active"`.
 *
 *   <timeline-ui>
 *     <timeline-item-ui text="Shipped"   time="2h ago" status="completed"></timeline-item-ui>
 *     <timeline-item-ui text="Delivery"  time="now"    status="active" spinner></timeline-item-ui>
 *     <timeline-item-ui text="Received"></timeline-item-ui>
 *   </timeline-ui>
 *
 * For agent reasoning / pipeline views, set size="sm" and use
 *   duration, outcomes, spinner, status="error"
 *
 *   <timeline-ui size="sm">
 *     <timeline-item-ui text="search" duration="850ms" status="completed"></timeline-item-ui>
 *     <timeline-item-ui text="generate" status="active" spinner></timeline-item-ui>
 *   </timeline-ui>
 *
 * For wizard / numbered-circle patterns, use the dedicated <stepper-ui>.
 *
 * Attributes (container):
 *   orientation — vertical (default) | horizontal
 *   size        — md (default) | sm
 *
 * Attributes (item):
 *   text        — primary label
 *   description — secondary text (optional)
 *   time        — right-aligned timestamp (optional; mutually exclusive with duration)
 *   duration    — right-aligned duration label (e.g. "850ms", "2s"); also set when live=true
 *   icon        — icon-ui name (replaces the dot when set)
 *   variant     — default | success | accent | warning | danger  (colors the dot/icon)
 *   completed   — boolean; renders "done" state
 *   active      — boolean; renders "active" state
 *   error       — boolean; renders "error" state (red dot)
 *   spinner     — boolean; spinning dot while active
 *
 * JS (item):
 *   .outcomes = string[]    // renders an expandable sub-list under the row
 */

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

// ── Container ──────────────────────────────────────────────────

export class UITimeline extends UIElement {
  static properties = {
    orientation: { type: String, default: 'vertical', reflect: true },
    size:        { type: String, default: 'md',       reflect: true },
  };

  static template = () => null;

  render() {
    const items = [...this.querySelectorAll(':scope > timeline-item-ui')];
    for (const item of items) item.removeAttribute('data-last');
    const last = items[items.length - 1];
    if (last) last.setAttribute('data-last', '');
  }
}

export class UITimelineItem extends UIElement {
  static properties = {
    text:        { type: String,  default: '',        reflect: true },
    description: { type: String,  default: '',        reflect: true },
    time:        { type: String,  default: '',        reflect: true },
    duration:    { type: String,  default: '',        reflect: true },
    icon:        { type: String,  default: '',        reflect: true },
    variant:     { type: String,  default: 'default', reflect: true },
    status:      { type: String,  default: 'idle',    reflect: true },
    spinner:     { type: Boolean, default: false,     reflect: true },
  };

  // §205 (v0.5.7): dynamic caret icons stamped on expanded-state ternary
  // (timeline.class.js:167). Per FEEDBACK-16 §1 + §209 slot-11 ternary-walker discovery.
  // Note: `this.icon` consumer-supplied — not declared here.
  static requiredIcons = ['caret-down', 'caret-right'];

  static template = () => null;

  #outcomes = [];
  #expanded = false;

  get outcomes() { return this.#outcomes; }
  set outcomes(v) {
    this.#outcomes = Array.isArray(v) ? v.slice() : [];
    this.render();
  }

  connected() {
    if (!logicalSlotted(this, 'label').length) {
      // Author provided just text/time — stamp the default slot structure
      this.innerHTML = `
        <span slot="label"></span>
        <span slot="description"></span>
        <span slot="time"></span>
      `;
    }
  }

  render() {
    const label = this.querySelector(':scope > [slot="label"]');
    const desc  = this.querySelector(':scope > [slot="description"]');
    const time  = this.querySelector(':scope > [slot="time"]');
    if (label) label.textContent = this.text;
    if (desc)  desc.textContent  = this.description;
    if (time)  time.textContent  = this.duration || this.time;

    if (this.icon) {
      let iconEl = this.querySelector(':scope > [slot="icon"]');
      if (!iconEl) {
        iconEl = document.createElement('icon-ui');
        iconEl.setAttribute('slot', 'icon');
        this.prepend(iconEl);
      }
      iconEl.setAttribute('name', this.icon);
    } else {
      this.querySelector(':scope > [slot="icon"]')?.remove();
    }

    // Outcomes sub-list + toggle caret
    let body = this.querySelector(':scope > [slot="outcomes"]');
    if (this.#outcomes.length > 0) {
      if (!body) {
        body = document.createElement('ul');
        body.setAttribute('slot', 'outcomes');
        this.appendChild(body);
      }
      body.innerHTML = '';
      for (const o of this.#outcomes) {
        const li = document.createElement('li');
        li.textContent = o;
        body.appendChild(li);
      }
      body.hidden = !this.#expanded;

      // Toggle caret lives on the row — we stamp a button once
      let toggle = this.querySelector(':scope > [data-timeline-toggle]');
      if (!toggle) {
        toggle = document.createElement('button');
        toggle.type = 'button';
        toggle.setAttribute('data-timeline-toggle', '');
        toggle.setAttribute('aria-label', 'Toggle details');
        toggle.addEventListener('click', (e) => {
          e.stopPropagation();
          this.#expanded = !this.#expanded;
          this.render();
          this.dispatchEvent(new CustomEvent('timeline-toggle', {
            bubbles: true, detail: { expanded: this.#expanded },
          }));
        });
        this.appendChild(toggle);
      }
      toggle.innerHTML = '';
      const caret = document.createElement('icon-ui');
      caret.setAttribute('name', this.#expanded ? 'caret-down' : 'caret-right');
      caret.setAttribute('color', 'muted');
      caret.setAttribute('size', 'sm');
      toggle.appendChild(caret);
    } else {
      this.querySelector(':scope > [data-timeline-toggle]')?.remove();
      body?.remove();
    }
  }
}
