"""Keyboard input modes for TUI pages (navigation vs text entry)."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal, Protocol

from unicurses import (  # type: ignore[import-untyped]
	KEY_DOWN,
	KEY_ENTER,
	KEY_UP,
)

from pygittools.tui.changes_list import ChangesList
from pygittools.tui.pages.branches import branch_picker_page
from pygittools.tui.pages.help import help_page
from pygittools.tui.pages.projects import projects_page
from pygittools.tui.types import PageAction, PageContext, PageResult

_KEY_ESC = 27
_HeaderFocus = Literal["changes", "repo", "branch"]


@dataclass(frozen=True, slots=True)
class ContextDispatch:
	page_result: PageResult | None = None
	next_mode: Literal["nav", "input"] | None = None


class PageInputHost(Protocol):
	@property
	def header_focus(self) -> _HeaderFocus: ...

	def set_header_focus(self, focus: _HeaderFocus) -> None: ...

	@property
	def page_context(self) -> PageContext | None: ...

	@property
	def changes(self) -> ChangesList: ...


class NavContext:
	def status_hint(self, host: PageInputHost) -> str:
		if host.header_focus == "repo":
			return "Enter browse projects — j/k move"
		if host.header_focus == "branch":
			return "Enter switch branch — j/k move"
		return host.changes.status_hint()

	def dispatch_key(self, host: PageInputHost, key: int) -> ContextDispatch:
		if key in (ord("h"), ord("H")):
			return ContextDispatch(page_result=PageResult(action=PageAction.PUSH, next_page=help_page()))

		if host.header_focus == "repo":
			if key in (KEY_DOWN, ord("j"), ord("J")):
				host.set_header_focus("branch")
			elif key in (KEY_ENTER, 10, 13):
				return ContextDispatch(page_result=PageResult(action=PageAction.PUSH, next_page=projects_page()))
			return ContextDispatch()

		if host.header_focus == "branch":
			if key in (KEY_UP, ord("k"), ord("K")):
				host.set_header_focus("repo")
			elif key in (KEY_DOWN, ord("j"), ord("J")):
				host.set_header_focus("changes")
			elif key in (KEY_ENTER, 10, 13):
				return ContextDispatch(page_result=PageResult(action=PageAction.PUSH, next_page=branch_picker_page()))
			return ContextDispatch()

		if key in (KEY_UP, ord("k"), ord("K")) and host.changes.is_at_top():
			host.set_header_focus("branch")
			return ContextDispatch()

		ctx = host.page_context
		if ctx is None:
			return ContextDispatch()
		nav_result = host.changes.handle_nav_key(key, ctx.repo)
		if nav_result.enter_input:
			return ContextDispatch(next_mode="input")
		return ContextDispatch()


class InputContext:
	def status_hint(self, host: PageInputHost) -> str:
		del host
		return "Esc relinquish input — Enter commit"

	def dispatch_key(self, host: PageInputHost, key: int) -> ContextDispatch:
		if key == _KEY_ESC:
			return ContextDispatch(next_mode="nav")
		ctx = host.page_context
		if ctx is not None:
			result = host.changes.handle_input_key(key, ctx.repo)
			if result.relinquish:
				return ContextDispatch(next_mode="nav")
		return ContextDispatch()


InputMode = NavContext | InputContext


def nav_context() -> NavContext:
	return NavContext()


def input_context() -> InputContext:
	return InputContext()