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

/**
 * <empty-state-ui icon="magnifying-glass" heading="No results" description="Try adjusting your search.">
 *   <button-ui slot="action" text="Clear filters" variant="outline"></button-ui>
 * </empty-state-ui>
 *
 * Placeholder for empty views — icon, heading, description, and action slot.
 * The action slot is user-provided (not stamped by the component).
 *
 * Note: Uses 'heading' attribute instead of 'title' to avoid native tooltip.
 */

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

export class UIEmptyState extends UIElement {
  static properties = {
    icon:        { type: String,  default: '',    reflect: true },
    heading:     { type: String,  default: '',    reflect: true },
    description: { type: String,  default: '',    reflect: true },
    // Semantic variant — yaml documented reflect:true since v1.
    variant:     { type: String,  default: '',    reflect: true },
    // §223 (v0.5.9): minimal layout — single-line muted (no centered column,
    // no padding bump, no icon-size lg). Use for inline empty-table-row /
    // inline placeholder cells where the canvas placeholder is too loud.
    minimal:     { type: Boolean, default: false, reflect: true },
  };

  static template = () => null;

  #iconEl = null;
  #headingEl = null;
  #descEl = null;

  // Mark slot elements we create so render() never overrides consumer-provided ones.
  // See ADR-0010 (slot content is source of truth).
  #stampMark(el) { el.dataset.emptyStateStamped = '1'; return el; }
  #wasStamped(el) { return el?.dataset?.emptyStateStamped === '1'; }

  connected() {
    this.#iconEl = this.querySelector(':scope > [slot="icon"]');
    if (!this.#iconEl) {
      this.#iconEl = this.#stampMark(document.createElement('icon-ui'));
      this.#iconEl.setAttribute('slot', 'icon');
      // §223 (v0.5.9): minimal layout sizes the icon inline; non-minimal
      // keeps the canonical lg badge.
      if (!this.minimal) this.#iconEl.setAttribute('size', 'lg');
      this.insertBefore(this.#iconEl, this.firstChild);
    }

    this.#headingEl = this.querySelector(':scope > [slot="heading"]');
    if (!this.#headingEl) {
      this.#headingEl = this.#stampMark(document.createElement('span'));
      this.#headingEl.setAttribute('slot', 'heading');
      this.insertBefore(this.#headingEl, this.querySelector('[slot="action"]'));
    }

    this.#descEl = this.querySelector(':scope > [slot="description"]');
    if (!this.#descEl) {
      this.#descEl = this.#stampMark(document.createElement('span'));
      this.#descEl.setAttribute('slot', 'description');
      this.insertBefore(this.#descEl, this.querySelector('[slot="action"]'));
    }
  }

  render() {
    if (!this.#iconEl) return;

    // Icon — only mutate stamped elements; visibility follows the source of truth.
    if (this.#wasStamped(this.#iconEl)) {
      if (this.icon) {
        this.#iconEl.setAttribute('name', this.icon);
        this.#iconEl.hidden = false;
      } else {
        this.#iconEl.hidden = true;
      }
    }

    // Heading — same policy.
    if (this.#wasStamped(this.#headingEl)) {
      if (this.heading) {
        this.#headingEl.textContent = this.heading;
        this.#headingEl.hidden = false;
      } else {
        this.#headingEl.hidden = true;
      }
    }

    // Description — same policy.
    if (this.#wasStamped(this.#descEl)) {
      if (this.description) {
        this.#descEl.textContent = this.description;
        this.#descEl.hidden = false;
      } else {
        this.#descEl.hidden = true;
      }
    }
  }

  disconnected() {
    this.#iconEl = null;
    this.#headingEl = null;
    this.#descEl = null;
  }
}
