"""Keyboard helpers for pyratatui KeyEvent values."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Protocol, runtime_checkable

_vim_enabled: bool = False


@runtime_checkable
class KeyLike(Protocol):
    @property
    def code(self) -> str: ...

    @property
    def ctrl(self) -> bool: ...

    @property
    def alt(self) -> bool: ...

    @property
    def shift(self) -> bool: ...


@dataclass(frozen=True, slots=True)
class Key:
    """Test-friendly stand-in for ``pyratatui.KeyEvent``."""

    code: str
    ctrl: bool = False
    alt: bool = False
    shift: bool = False


def key(code: str, *, ctrl: bool = False, alt: bool = False, shift: bool = False) -> Key:
    return Key(code=code, ctrl=ctrl, alt=alt, shift=shift)


def set_vim_enabled(enabled: bool) -> None:
    global _vim_enabled
    _vim_enabled = enabled


def vim_enabled() -> bool:
    return _vim_enabled


def is_quit(ev: KeyLike) -> bool:
    return ev.code.casefold() == "q" or (ev.code == "c" and ev.ctrl)


def is_up(ev: KeyLike) -> bool:
    if ev.code == "Up":
        return True
    return _vim_enabled and ev.code in {"k", "K"}


def is_down(ev: KeyLike) -> bool:
    if ev.code == "Down":
        return True
    return _vim_enabled and ev.code in {"j", "J"}


def is_left(ev: KeyLike) -> bool:
    if ev.code == "Left":
        return True
    return _vim_enabled and ev.code in {"h", "H"}


def is_right(ev: KeyLike) -> bool:
    if ev.code == "Right":
        return True
    return _vim_enabled and ev.code in {"l", "L"}


def is_enter(ev: KeyLike) -> bool:
    return ev.code == "Enter"


def is_esc(ev: KeyLike) -> bool:
    return ev.code == "Esc"


def is_tab(ev: KeyLike) -> bool:
    return ev.code == "Tab" and not ev.shift


def is_backtab(ev: KeyLike) -> bool:
    return ev.code in {"BackTab", "Backtab"} or (ev.code == "Tab" and ev.shift)


def is_backspace(ev: KeyLike) -> bool:
    return ev.code == "Backspace"


def is_space(ev: KeyLike) -> bool:
    return ev.code == " "


def is_slash(ev: KeyLike) -> bool:
    return ev.code == "/" and not ev.ctrl and not ev.alt


def printable_char(ev: KeyLike) -> str | None:
    if ev.ctrl or ev.alt:
        return None
    if len(ev.code) == 1 and ev.code.isprintable():
        return ev.code
    return None


def move_hint() -> str:
    return "j/k move" if _vim_enabled else "arrows move"


def tab_hint() -> str:
    return "H/L switch tab" if _vim_enabled else "←/→ switch tab"


def board_hint() -> str:
    return "H/L switch board" if _vim_enabled else "←/→ switch board"