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

/**
 * <badge-ui text="New" variant="accent"></badge-ui>
 * <badge-ui text="3" variant="danger" size="sm"></badge-ui>
 * <badge-ui text="Organic" variant="accent" icon="dot"></badge-ui>  ← chart legend chip
 * <badge-ui status="beta"></badge-ui>                                ← status shorthand
 *
 * Inline badge / tag. Pill-shaped, text rendered via CSS attr().
 *
 * Variants: default, accent, info, success, warning, danger, primary, muted, neutral
 * Sizes: sm, md (default)
 * Icon: optional leading icon (any registered icon name; "dot" for legend
 *       markers). Inherits the variant's foreground color so legend chips
 *       read as a single visual unit instead of icon + label collage.
 * Status: semantic shorthand that auto-maps variant + text.
 */

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

const STATUS_MAP = {
  new:        { variant: 'success', text: 'New' },
  updated:    { variant: 'info',    text: 'Updated' },
  deprecated: { variant: 'warning', text: 'Deprecated' },
  removed:    { variant: 'danger',  text: 'Removed' },
  beta:       { variant: 'accent',  text: 'Beta' },
};

export class UIBadge extends UIElement {
  static properties = {
    text:    { type: String,  default: '', reflect: true },
    // NOTE: `textContent` is intentionally NOT declared as a reactive
    // prop — `installProps()` would override the native DOM setter, so
    // `el.textContent = '…'` would silently no-op. Yaml keeps the prop
    // entry for renderer metadata, but the JS class must not declare
    // it. v0.5.x §327.
    variant: { type: String,  default: 'default', reflect: true },
    size:    { type: String,  default: 'md', reflect: true },
    icon:    { type: String,  default: '',        reflect: true },
    status:  { type: String,  default: '',        reflect: true },
  };

  static template = () => null;

  connected() {
    /* Default role is `status` (matches badge's "passive callout" semantic
       — a screen reader announces the badge text as a state without
       interrupting). Consumers that wire interactivity (e.g.
       `<chart-legend-ui>` toggling series) are free to set
       `role="button"` (or any other role) before connection — we don't
       overwrite an explicit consumer choice. */
    if (!this.hasAttribute('role')) {
      this.setAttribute('role', 'status');
    }
  }

  render() {
    // Status shorthand wins over explicit variant/text while it's set —
    // mixing is unsupported. Converges in one extra render pass.
    if (this.status) {
      const entry = STATUS_MAP[this.status];
      if (entry) {
        if (this.variant !== entry.variant) this.variant = entry.variant;
        if (this.text !== entry.text) this.text = entry.text;
      }
    }

    if (this.text) this.setAttribute('aria-label', this.text);

    // Stamp / update the leading icon. Pattern mirrors button-ui so the same
    // icon-ui element handles loading + cleanup; we just `prepend` so the icon
    // sits before the CSS-rendered text (text is `:scope::after { content }`).
    if (this.icon) {
      const existing = this.querySelector(':scope > icon-ui');
      if (!existing || existing.getAttribute('name') !== this.icon) {
        if (existing) existing.remove();
        const iconEl = document.createElement('icon-ui');
        iconEl.setAttribute('name', this.icon);
        iconEl.setAttribute('size', 'sm');
        this.prepend(iconEl);
      }
    } else {
      this.querySelector(':scope > icon-ui')?.remove();
    }
  }
}
