import { describe, it, expect, beforeEach } from 'vitest';
import { focusable } from './focusable.js';
import { mountHost, connectTrait, resetDOM } from '../test-helpers.js';

describe('focusable', () => {
  beforeEach(resetDOM);

  it('keyboard focus → sets data-focusable-keyboard', () => {
    const host = mountHost();
    connectTrait(focusable, host);
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(true);
  });

  it('mouse focus → does NOT set data-focusable-keyboard', () => {
    const host = mountHost();
    connectTrait(focusable, host);
    host.dispatchEvent(new MouseEvent('mousedown'));
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(false);
  });

  it('blur clears the attribute', () => {
    const host = mountHost();
    connectTrait(focusable, host);
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(true);
    host.dispatchEvent(new FocusEvent('blur'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(false);
  });

  it('mousedown→blur→keyboard-focus correctly distinguishes the second visit', () => {
    const host = mountHost();
    connectTrait(focusable, host);
    // First visit via mouse
    host.dispatchEvent(new MouseEvent('mousedown'));
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(false);
    host.dispatchEvent(new FocusEvent('blur'));
    // Second visit via keyboard
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(true);
  });

  it('disconnect clears attribute and removes listeners', () => {
    const host = mountHost();
    const inst = connectTrait(focusable, host);
    host.dispatchEvent(new FocusEvent('focus'));
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(true);
    inst.disconnect(host);
    expect(host.hasAttribute('data-focusable-keyboard')).toBe(false);
  });
});
