// Integration coverage for the client HID keymap contract.
//
// Scope: exercise the public keycode and modifier helpers through the
// root test harness crate instead of package-local integration tests.
// Targets: `client/src/input/keymap.rs` and its shared-character delegation.
// Why: the full keyboard map is large enough that one dedicated contract test
// is clearer than scattering smoke coverage across unrelated crates.

use evdev::KeyCode;
use lesavka_client::input::keymap::{char_to_usage, is_modifier, keycode_to_usage};

#[test]
fn keycode_to_usage_covers_each_supported_keyboard_block() {
    let cases = [
        (KeyCode::KEY_A, 0x04),
        (KeyCode::KEY_B, 0x05),
        (KeyCode::KEY_C, 0x06),
        (KeyCode::KEY_D, 0x07),
        (KeyCode::KEY_E, 0x08),
        (KeyCode::KEY_F, 0x09),
        (KeyCode::KEY_G, 0x0A),
        (KeyCode::KEY_H, 0x0B),
        (KeyCode::KEY_I, 0x0C),
        (KeyCode::KEY_J, 0x0D),
        (KeyCode::KEY_K, 0x0E),
        (KeyCode::KEY_L, 0x0F),
        (KeyCode::KEY_M, 0x10),
        (KeyCode::KEY_N, 0x11),
        (KeyCode::KEY_O, 0x12),
        (KeyCode::KEY_P, 0x13),
        (KeyCode::KEY_Q, 0x14),
        (KeyCode::KEY_R, 0x15),
        (KeyCode::KEY_S, 0x16),
        (KeyCode::KEY_T, 0x17),
        (KeyCode::KEY_U, 0x18),
        (KeyCode::KEY_V, 0x19),
        (KeyCode::KEY_W, 0x1A),
        (KeyCode::KEY_X, 0x1B),
        (KeyCode::KEY_Y, 0x1C),
        (KeyCode::KEY_Z, 0x1D),
        (KeyCode::KEY_1, 0x1E),
        (KeyCode::KEY_2, 0x1F),
        (KeyCode::KEY_3, 0x20),
        (KeyCode::KEY_4, 0x21),
        (KeyCode::KEY_5, 0x22),
        (KeyCode::KEY_6, 0x23),
        (KeyCode::KEY_7, 0x24),
        (KeyCode::KEY_8, 0x25),
        (KeyCode::KEY_9, 0x26),
        (KeyCode::KEY_0, 0x27),
        (KeyCode::KEY_ENTER, 0x28),
        (KeyCode::KEY_ESC, 0x29),
        (KeyCode::KEY_BACKSPACE, 0x2A),
        (KeyCode::KEY_TAB, 0x2B),
        (KeyCode::KEY_SPACE, 0x2C),
        (KeyCode::KEY_MINUS, 0x2D),
        (KeyCode::KEY_EQUAL, 0x2E),
        (KeyCode::KEY_LEFTBRACE, 0x2F),
        (KeyCode::KEY_RIGHTBRACE, 0x30),
        (KeyCode::KEY_BACKSLASH, 0x31),
        (KeyCode::KEY_SEMICOLON, 0x33),
        (KeyCode::KEY_APOSTROPHE, 0x34),
        (KeyCode::KEY_GRAVE, 0x35),
        (KeyCode::KEY_COMMA, 0x36),
        (KeyCode::KEY_DOT, 0x37),
        (KeyCode::KEY_SLASH, 0x38),
        (KeyCode::KEY_CAPSLOCK, 0x39),
        (KeyCode::KEY_F1, 0x3A),
        (KeyCode::KEY_F2, 0x3B),
        (KeyCode::KEY_F3, 0x3C),
        (KeyCode::KEY_F4, 0x3D),
        (KeyCode::KEY_F5, 0x3E),
        (KeyCode::KEY_F6, 0x3F),
        (KeyCode::KEY_F7, 0x40),
        (KeyCode::KEY_F8, 0x41),
        (KeyCode::KEY_F9, 0x42),
        (KeyCode::KEY_F10, 0x43),
        (KeyCode::KEY_F11, 0x44),
        (KeyCode::KEY_F12, 0x45),
        (KeyCode::KEY_SYSRQ, 0x46),
        (KeyCode::KEY_SCROLLLOCK, 0x47),
        (KeyCode::KEY_PAUSE, 0x48),
        (KeyCode::KEY_INSERT, 0x49),
        (KeyCode::KEY_HOME, 0x4A),
        (KeyCode::KEY_PAGEUP, 0x4B),
        (KeyCode::KEY_DELETE, 0x4C),
        (KeyCode::KEY_END, 0x4D),
        (KeyCode::KEY_PAGEDOWN, 0x4E),
        (KeyCode::KEY_RIGHT, 0x4F),
        (KeyCode::KEY_LEFT, 0x50),
        (KeyCode::KEY_DOWN, 0x51),
        (KeyCode::KEY_UP, 0x52),
        (KeyCode::KEY_NUMLOCK, 0x53),
        (KeyCode::KEY_KPSLASH, 0x54),
        (KeyCode::KEY_KPASTERISK, 0x55),
        (KeyCode::KEY_KPMINUS, 0x56),
        (KeyCode::KEY_KPPLUS, 0x57),
        (KeyCode::KEY_KPENTER, 0x58),
        (KeyCode::KEY_KP1, 0x59),
        (KeyCode::KEY_KP2, 0x5A),
        (KeyCode::KEY_KP3, 0x5B),
        (KeyCode::KEY_KP4, 0x5C),
        (KeyCode::KEY_KP5, 0x5D),
        (KeyCode::KEY_KP6, 0x5E),
        (KeyCode::KEY_KP7, 0x5F),
        (KeyCode::KEY_KP8, 0x60),
        (KeyCode::KEY_KP9, 0x61),
        (KeyCode::KEY_KP0, 0x62),
        (KeyCode::KEY_KPDOT, 0x63),
        (KeyCode::KEY_KPEQUAL, 0x67),
        (KeyCode::KEY_102ND, 0x64),
        (KeyCode::KEY_MENU, 0x65),
    ];

    for (key, usage) in cases {
        assert_eq!(
            keycode_to_usage(key),
            Some(usage),
            "unexpected mapping for {key:?}"
        );
    }

    assert_eq!(keycode_to_usage(KeyCode::KEY_LEFTCTRL), None);
    assert_eq!(keycode_to_usage(KeyCode::KEY_RESERVED), None);
}

#[test]
fn is_modifier_covers_each_supported_modifier_bit() {
    let cases = [
        (KeyCode::KEY_LEFTCTRL, 0x01),
        (KeyCode::KEY_LEFTSHIFT, 0x02),
        (KeyCode::KEY_LEFTALT, 0x04),
        (KeyCode::KEY_LEFTMETA, 0x08),
        (KeyCode::KEY_RIGHTCTRL, 0x10),
        (KeyCode::KEY_RIGHTSHIFT, 0x20),
        (KeyCode::KEY_RIGHTALT, 0x40),
        (KeyCode::KEY_RIGHTMETA, 0x80),
    ];

    for (key, mask) in cases {
        assert_eq!(
            is_modifier(key),
            Some(mask),
            "unexpected modifier for {key:?}"
        );
    }

    assert_eq!(is_modifier(KeyCode::KEY_A), None);
}

#[test]
fn char_to_usage_exposes_shared_hid_mapping_from_the_client_surface() {
    assert_eq!(char_to_usage('a'), Some((0x04, 0x00)));
    assert_eq!(char_to_usage('A'), Some((0x04, 0x02)));
    assert_eq!(char_to_usage('0'), Some((0x27, 0x00)));
    assert_eq!(char_to_usage('!'), Some((0x1E, 0x02)));
    assert_eq!(char_to_usage('?'), Some((0x38, 0x02)));
    assert_eq!(char_to_usage('\t'), Some((0x2B, 0x00)));
    assert_eq!(char_to_usage('\n'), Some((0x28, 0x00)));
    assert_eq!(char_to_usage('é'), None);
}
