/**
 * Tests for services/keyboard.js
 *
 * Tests the keyboard shortcut matching logic and service API.
 * We can't test the full initialization (which binds to document),
 * but we can test the shortcut matching and public API.
 */

// Stub URLS needed by keyboard.js handlers
window.URLS = {
    PAGES: {
        HOME: '/',
        HISTORY: '/history/',
        METRICS: '/metrics/',
        SETTINGS: '/settings/',
    }
};

import '@js/services/keyboard.js';

const KS = window.KeyboardService;

describe('KeyboardService', () => {
    describe('shortcuts registry invariants', () => {
        it('every registered shortcut has a callable handler', () => {
            // Catches accidental refactors that drop the handler field.
            const shortcuts = KS.shortcuts();
            for (const [name, shortcut] of Object.entries(shortcuts)) {
                expect(shortcut.handler, `${name} missing handler`).toBeTypeOf('function');
                expect(shortcut.keys, `${name} missing keys`).toBeInstanceOf(Array);
                expect(shortcut.keys.length, `${name} has empty keys`).toBeGreaterThan(0);
            }
        });
    });

    describe('addShortcut / removeShortcut', () => {
        afterEach(() => {
            KS.removeShortcut('testShortcut');
        });

        it('adds a custom shortcut', () => {
            KS.addShortcut('testShortcut', {
                keys: ['ctrl+t'],
                description: 'Test shortcut',
                handler: () => {}
            });
            const shortcuts = KS.shortcuts();
            expect(shortcuts.testShortcut).toBeDefined();
            expect(shortcuts.testShortcut.keys).toEqual(['ctrl+t']);
        });

        it('removes a custom shortcut', () => {
            KS.addShortcut('testShortcut', {
                keys: ['ctrl+t'],
                description: 'Test',
                handler: () => {}
            });
            KS.removeShortcut('testShortcut');
            const shortcuts = KS.shortcuts();
            expect(shortcuts.testShortcut).toBeUndefined();
        });
    });

    describe('keyboard event handling', () => {
        it('Escape key triggers newSearch shortcut', () => {
            // The shortcut sets window.location.href, which we can spy on
            const originalHref = window.location.href;

            // Create a keydown event for Escape
            const event = new KeyboardEvent('keydown', {
                key: 'Escape',
                code: 'Escape',
                bubbles: true,
            });

            // We can verify the event doesn't throw
            expect(() => document.dispatchEvent(event)).not.toThrow();
        });

        it('ignores shortcuts when typing in input fields', () => {
            const input = document.createElement('input');
            input.type = 'text';
            document.body.appendChild(input);
            input.focus();

            const event = new KeyboardEvent('keydown', {
                key: 'Escape',
                code: 'Escape',
                bubbles: true,
            });

            // Should not throw or cause navigation when typing
            expect(() => input.dispatchEvent(event)).not.toThrow();
            input.remove();
        });

        it('allows Ctrl+Shift navigation shortcuts even in input', () => {
            const input = document.createElement('input');
            input.type = 'text';
            document.body.appendChild(input);
            input.focus();

            const event = new KeyboardEvent('keydown', {
                key: '1',
                code: 'Digit1',
                ctrlKey: true,
                shiftKey: true,
                bubbles: true,
            });

            // Should not throw
            expect(() => input.dispatchEvent(event)).not.toThrow();
            input.remove();
        });
    });

});
