/**
 * <traits-host> behavior tests — focus on the wrapper-specific contract:
 *  - children pass through visually (display: contents)
 *  - declarative traits attach to the wrapper
 *  - traits attribute swaps work the same as on UIElement subclasses
 *  - events from children bubble up to the wrapper for trait capture
 */

import { describe, it, expect, beforeEach } from 'vitest';
import './traits-host.js';
import './pressable/pressable.js';
import './hoverable/hoverable.js';
import { resetDOM } from './test-helpers.js';

describe('<traits-host>', () => {
  beforeEach(resetDOM);

  it('is registered as a UIElement subclass', () => {
    const ctor = customElements.get('traits-host');
    expect(ctor).toBeTruthy();
  });

  it('declarative traits=" " attaches to the wrapper itself', () => {
    document.body.innerHTML = '<traits-host traits="pressable"><div>Raw</div></traits-host>';
    const host = document.body.firstElementChild;
    host.dispatchEvent(new PointerEvent('pointerdown'));
    expect(host.hasAttribute('data-pressable-pressed')).toBe(true);
    host.dispatchEvent(new PointerEvent('pointerup'));
    expect(host.hasAttribute('data-pressable-pressed')).toBe(false);
  });

  it('events from children bubble up so the trait captures them', () => {
    document.body.innerHTML = '<traits-host traits="hoverable"><span class="inner">Hover</span></traits-host>';
    const host = document.body.firstElementChild;
    const inner = host.querySelector('.inner');
    // Synthesize a pointerenter on the wrapper (DOM bubbling up from inner
    // would also work but happy-dom doesn't always reflect that for hover).
    host.dispatchEvent(new PointerEvent('pointerenter', { bubbles: true }));
    expect(host.hasAttribute('data-hoverable-hover')).toBe(true);
    host.dispatchEvent(new PointerEvent('pointerleave', { bubbles: true }));
    expect(host.hasAttribute('data-hoverable-hover')).toBe(false);
  });

  it('changing traits attribute swaps the trait stack', () => {
    document.body.innerHTML = '<traits-host traits="pressable"><div>x</div></traits-host>';
    const host = document.body.firstElementChild;
    host.dispatchEvent(new PointerEvent('pointerdown'));
    expect(host.hasAttribute('data-pressable-pressed')).toBe(true);
    host.dispatchEvent(new PointerEvent('pointerup'));

    host.setAttribute('traits', 'hoverable');
    host.dispatchEvent(new PointerEvent('pointerdown'));
    expect(host.hasAttribute('data-pressable-pressed')).toBe(false);
    host.dispatchEvent(new PointerEvent('pointerenter'));
    expect(host.hasAttribute('data-hoverable-hover')).toBe(true);
  });

  it('removing the host cleans up trait attributes', () => {
    document.body.innerHTML = '<traits-host traits="pressable"><div>x</div></traits-host>';
    const host = document.body.firstElementChild;
    host.dispatchEvent(new PointerEvent('pointerdown'));
    expect(host.hasAttribute('data-pressable-pressed')).toBe(true);
    host.remove();
    expect(host.hasAttribute('data-pressable-pressed')).toBe(false);
  });

  it('with no traits attribute: pure pass-through, children render', () => {
    document.body.innerHTML = '<traits-host><span class="x">child</span></traits-host>';
    const host = document.body.firstElementChild;
    expect(host.querySelector('.x')).toBeTruthy();
    expect(host.querySelector('.x').textContent).toBe('child');
  });
});
