/**
 * stat-ui — focused unit tests for the v0.6.18 `loading` boolean prop
 * (FB-12 P2 resolution).
 *
 * Pre-v0.6.18: stat-ui rendered empty/zero values during data fetch with no
 * visual indication. Consumers were forced to hand-roll skeleton-card
 * workarounds with their own `@keyframes` CSS — duplicating skeleton-ui.
 *
 * v0.6.18 adds `loading: Boolean`. When set:
 *   - value + change slots render <skeleton-ui> shimmer placeholders
 *   - aria-busy="true" on the host
 *   - label + icon (static metadata) are preserved
 *   - toggling off restores text content + clears aria-busy
 */

import { describe, it, expect, beforeEach } from 'vitest';
import '../../core/element.js';
import './stat.js';
// skeleton-ui is referenced by stat-ui at runtime when [loading]; load it so
// the element gets defined (otherwise the inner <skeleton-ui> stays an
// HTMLUnknownElement, which is still observable in the DOM but the assertions
// below want to confirm registration via tagName.)
import '../skeleton/skeleton.js';

const tick = () => new Promise((r) => queueMicrotask(r));

function mount(html) {
  const wrap = document.createElement('div');
  wrap.innerHTML = html;
  document.body.appendChild(wrap);
  return wrap.firstElementChild;
}

describe('stat-ui — v0.6.18 loading prop (FB-12 P2)', () => {
  beforeEach(() => { document.body.innerHTML = ''; });

  it('defaults loading to false; no aria-busy on host', async () => {
    const el = mount('<stat-ui label="Total" value="1,234"></stat-ui>');
    await tick();
    expect(el.loading).toBe(false);
    expect(el.hasAttribute('loading')).toBe(false);
    expect(el.getAttribute('aria-busy')).toBeNull();
  });

  it('reflects [loading] attribute to the property', () => {
    const el = mount('<stat-ui label="Total" loading></stat-ui>');
    expect(el.loading).toBe(true);
    expect(el.hasAttribute('loading')).toBe(true);
  });

  it('sets aria-busy="true" on host when [loading]', async () => {
    const el = mount('<stat-ui label="Total" loading></stat-ui>');
    await tick();
    expect(el.getAttribute('aria-busy')).toBe('true');
  });

  it('renders a <skeleton-ui> inside the value slot when [loading]', async () => {
    const el = mount('<stat-ui label="Total" loading></stat-ui>');
    await tick();
    const valueSlot = el.querySelector(':scope > [slot="value"]');
    expect(valueSlot).not.toBeNull();
    const sk = valueSlot.querySelector('skeleton-ui');
    expect(sk).not.toBeNull();
    expect(sk.tagName.toLowerCase()).toBe('skeleton-ui');
  });

  it('renders a <skeleton-ui> inside the change slot when [loading]', async () => {
    const el = mount('<stat-ui label="Total" loading></stat-ui>');
    await tick();
    const changeSlot = el.querySelector(':scope > [slot="change"]');
    expect(changeSlot).not.toBeNull();
    expect(changeSlot.hidden).toBe(false);
    const sk = changeSlot.querySelector('skeleton-ui');
    expect(sk).not.toBeNull();
  });

  it('preserves label text content when [loading] (label is static metadata)', async () => {
    const el = mount('<stat-ui label="Total Users" loading></stat-ui>');
    await tick();
    const labelSlot = el.querySelector(':scope > [slot="label"]');
    expect(labelSlot.textContent).toBe('Total Users');
  });

  it('restores value + change text + clears aria-busy when loading toggles off', async () => {
    const el = mount('<stat-ui label="Total" loading></stat-ui>');
    await tick();
    // Now flip off + add real values
    el.removeAttribute('loading');
    el.setAttribute('value', '1,234');
    el.setAttribute('change', '+12%');
    await tick();
    expect(el.getAttribute('aria-busy')).toBeNull();
    expect(el.querySelector(':scope > [slot="value"]').textContent).toBe('1,234');
    expect(el.querySelector(':scope > [slot="change"]').textContent).toBe('+12%');
    // skeleton-ui children should be gone (textContent setter clobbers innerHTML)
    expect(el.querySelector(':scope > [slot="value"] skeleton-ui')).toBeNull();
    expect(el.querySelector(':scope > [slot="change"] skeleton-ui')).toBeNull();
  });

  it('keeps icon visible when [loading] if icon prop is set', async () => {
    const el = mount('<stat-ui label="Total" icon="users" loading></stat-ui>');
    await tick();
    const iconSlot = el.querySelector(':scope > [slot="icon"]');
    expect(iconSlot).not.toBeNull();
    expect(iconSlot.hidden).toBe(false);
    expect(iconSlot.getAttribute('name')).toBe('users');
  });
});
