import { describe, it, expect, beforeEach } from 'vitest';
import '../../core/element.js';
import './demo-toggle.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('demo-toggle-ui', () => {
  beforeEach(() => { document.body.innerHTML = ''; });

  it('registers demo-toggle-ui as a custom element', () => {
    expect(customElements.get('demo-toggle-ui')).toBeDefined();
  });

  it('defaults to state="off" when [initial] is not set', async () => {
    const el = mount('<demo-toggle-ui></demo-toggle-ui>');
    await tick();
    expect(el.state).toBe('off');
    expect(el.getAttribute('state')).toBe('off');
  });

  it('honors [initial="on"] on connect', async () => {
    const el = mount('<demo-toggle-ui initial="on"></demo-toggle-ui>');
    await tick();
    expect(el.state).toBe('on');
  });

  it('renders the auto-stamped header bar with switch + label', async () => {
    const el = mount('<demo-toggle-ui label-on="Foo" label-off="Bar"></demo-toggle-ui>');
    await tick();
    const bar = el.querySelector('[slot="bar"]');
    const sw  = el.querySelector('[data-demo-toggle-switch]');
    const label = el.querySelector('[data-demo-toggle-label]');
    expect(bar).toBeTruthy();
    expect(sw).toBeTruthy();
    expect(label).toBeTruthy();
    // state defaults to "off"; label-off should be active
    expect(label.textContent).toBe('Bar');
  });

  it('toggle() flips state and emits change with detail.state', async () => {
    const el = mount('<demo-toggle-ui></demo-toggle-ui>');
    await tick();
    const events = [];
    el.addEventListener('change', (e) => events.push(e.detail));

    el.toggle();
    expect(el.state).toBe('on');
    expect(events).toHaveLength(1);
    expect(events[0]).toEqual({ state: 'on' });

    el.toggle();
    expect(el.state).toBe('off');
    expect(events).toHaveLength(2);
    expect(events[1]).toEqual({ state: 'off' });
  });

  it('clicking the embedded switch flips host state and bubbles change', async () => {
    const el = mount('<demo-toggle-ui></demo-toggle-ui>');
    await tick();
    const sw = el.querySelector('[data-demo-toggle-switch]');

    const events = [];
    el.addEventListener('change', (e) => events.push(e.detail));

    sw.click();
    await tick();
    expect(el.state).toBe('on');
    expect(events).toHaveLength(1);
    expect(events[0]).toEqual({ state: 'on' });
  });

  it('reflects state to the [state] attribute', async () => {
    const el = mount('<demo-toggle-ui initial="on"></demo-toggle-ui>');
    await tick();
    expect(el.getAttribute('state')).toBe('on');
    el.toggle();
    expect(el.getAttribute('state')).toBe('off');
  });

  it('coerces an invalid [state] attribute to "off"', async () => {
    const el = mount('<demo-toggle-ui state="garbage"></demo-toggle-ui>');
    await tick();
    expect(el.state).toBe('off');
  });

  it('updates the active label when state flips', async () => {
    const el = mount('<demo-toggle-ui label-on="With trait" label-off="Without trait"></demo-toggle-ui>');
    await tick();
    const label = el.querySelector('[data-demo-toggle-label]');
    expect(label.textContent).toBe('Without trait');
    el.toggle();
    await tick();
    expect(label.textContent).toBe('With trait');
  });
});
