import { beforeEach, afterEach, describe, it, expect, vi, afterAll, beforeAll } from 'vitest';
import { useFloatingItem } from './floating-item.svelte';
beforeAll(() => {
    vi.stubGlobal('matchMedia', (query) => ({
        matches: query.includes('max-width: 780px'),
        media: query,
        onchange: null,
        addEventListener: vi.fn(),
        removeEventListener: vi.fn(),
        dispatchEvent: vi.fn(),
    }));
});
afterAll(() => {
    vi.unstubAllGlobals();
});
describe('useFloatingItem', () => {
    let triggerEl;
    let floatingEl;
    let firstButton;
    let addSpy;
    let removeSpy;
    beforeEach(() => {
        triggerEl = document.createElement('button');
        triggerEl.textContent = 'trigger';
        document.body.appendChild(triggerEl);
        floatingEl = document.createElement('div');
        floatingEl.className = 'mc-sidebar__floating-item mc-sidebar__floating-item--hidden';
        firstButton = document.createElement('button');
        firstButton.textContent = 'first';
        floatingEl.appendChild(firstButton);
        document.body.appendChild(floatingEl);
        addSpy = vi.spyOn(document, 'addEventListener');
        removeSpy = vi.spyOn(document, 'removeEventListener');
    });
    afterEach(() => {
        vi.restoreAllMocks();
        document.body.innerHTML = '';
    });
    it('showFloatingItem removes hidden class and adds mousedown listener', () => {
        const { showFloatingItem } = useFloatingItem(() => triggerEl, () => floatingEl);
        showFloatingItem();
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(false);
        expect(addSpy).toHaveBeenCalledWith('mousedown', expect.any(Function));
    });
    it('hideFloatingItem hides and removes listener when relatedTarget is outside', () => {
        const { showFloatingItem, hideFloatingItem } = useFloatingItem(() => triggerEl, () => floatingEl);
        showFloatingItem();
        hideFloatingItem();
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(true);
        expect(removeSpy).toHaveBeenCalledWith('mousedown', expect.any(Function));
    });
    it('hideFloatingItem does not hide when relatedTarget is inside floating or trigger (allowItemHover)', () => {
        const { showFloatingItem, hideFloatingItem } = useFloatingItem(() => triggerEl, () => floatingEl, { allowItemHover: true });
        showFloatingItem();
        const evInsideFloating = { relatedTarget: firstButton };
        hideFloatingItem(evInsideFloating);
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(false);
        expect(removeSpy).not.toHaveBeenCalled();
    });
    it('clicking outside triggers hide via mousedown listener', () => {
        const { showFloatingItem } = useFloatingItem(() => triggerEl, () => floatingEl);
        showFloatingItem();
        const outside = document.createElement('div');
        document.body.appendChild(outside);
        outside.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(true);
    });
    it('onTriggerKeydown opens on ArrowDown and focuses first item', () => {
        const { onTriggerKeydown } = useFloatingItem(() => triggerEl, () => floatingEl);
        const preventSpy = vi.fn();
        const ev = { key: 'ArrowDown', preventDefault: preventSpy };
        const focusSpy = vi.spyOn(firstButton, 'focus');
        onTriggerKeydown(ev);
        expect(preventSpy).toHaveBeenCalled();
        expect(focusSpy).toHaveBeenCalled();
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(false);
    });
    it('onTriggerKeydown with Tab hides the floating item', () => {
        const { showFloatingItem, onTriggerKeydown } = useFloatingItem(() => triggerEl, () => floatingEl);
        showFloatingItem();
        const ev = { key: 'Tab' };
        onTriggerKeydown(ev);
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(true);
    });
    it('onListboxKeydown Escape hides and focuses trigger', () => {
        const { showFloatingItem, onListboxKeydown } = useFloatingItem(() => triggerEl, () => floatingEl);
        showFloatingItem();
        const preventSpy = vi.fn();
        const ev = { key: 'Escape', preventDefault: preventSpy };
        const focusSpy = vi.spyOn(triggerEl, 'focus');
        onListboxKeydown(ev);
        expect(preventSpy).toHaveBeenCalled();
        expect(focusSpy).toHaveBeenCalled();
        expect(floatingEl.classList.contains('mc-sidebar__floating-item--hidden')).toBe(true);
    });
});
