"""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"