"""Default landing page for the pgt TUI."""

from __future__ import annotations

import time
from pathlib import Path
from typing import Literal

from pyratatui import Constraint, Direction, Frame, Layout, Paragraph, Rect

from pygittools.actions import find_project_root, load_action_sets
from pygittools.tui.branches import current_branch_name
from pygittools.tui.changes_list import ChangesList
from pygittools.tui.commit_draft import load_commit_draft
from pygittools.tui.git_colors import current_theme, focus_style
from pygittools.tui.input_context import InputContext, InputMode, input_context, nav_context
from pygittools.tui.keys import KeyLike, is_quit
from pygittools.tui.log_list import CommitLogList
from pygittools.tui.project_label import repo_project_label
from pygittools.tui.tabs import render_tab_row
from pygittools.tui.tasks_list import TasksBoardList
from pygittools.tui.types import Page, PageAction, PageContext, PageResult
from pygittools.tui.worktrees_list import WorktreesList

_TABS: tuple[str, ...] = ("Status", "Log", "Tasks", "Worktrees")
_HeaderFocus = Literal["changes", "repo", "branch", "actions"]
_HomeTab = Literal["status", "log", "tasks", "worktrees"]
_TAB_KEYS: tuple[_HomeTab, ...] = ("status", "log", "tasks", "worktrees")
_IDLE_REFRESH_S = 10.0


class HomePage:
	title = "pgt"

	def __init__(self) -> None:
		self._ctx: PageContext | None = None
		self._changes = ChangesList()
		self._log = CommitLogList()
		self._tasks = TasksBoardList()
		self._worktrees = WorktreesList()
		self._active_tab: _HomeTab = "status"
		self._header_focus: _HeaderFocus = "changes"
		self._input_mode: InputMode = nav_context()
		self._action_sets: tuple[str, ...] = ()
		self._last_refresh_at = 0.0

	@property
	def header_focus(self) -> _HeaderFocus:
		return self._header_focus

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

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

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

	@property
	def log(self) -> CommitLogList:
		return self._log

	@property
	def tasks(self) -> TasksBoardList:
		return self._tasks

	@property
	def worktrees(self) -> WorktreesList:
		return self._worktrees

	@property
	def active_tab(self) -> _HomeTab:
		return self._active_tab

	@property
	def has_actions(self) -> bool:
		return bool(self._action_sets)

	def set_active_tab(self, tab: _HomeTab) -> None:
		self._active_tab = tab
		if tab != "status":
			if isinstance(self._input_mode, InputContext):
				self._input_mode = nav_context()
			if self._header_focus == "actions":
				self._header_focus = "changes"

	def refresh(self) -> None:
		self._refresh()

	def _refresh(self) -> None:
		ctx = self._ctx
		if ctx is None:
			return
		self._changes.refresh(ctx.repo)
		self._log.refresh(ctx.repo)
		self._tasks.refresh(ctx.repo)
		self._worktrees.refresh(ctx.repo)
		self._action_sets = _action_set_names(ctx)
		self._last_refresh_at = time.monotonic()

	def on_enter(self, ctx: PageContext) -> None:
		self._ctx = ctx
		self._active_tab = "status"
		self._header_focus = "changes"
		self._input_mode = nav_context()
		self._changes.set_commit_message(load_commit_draft(ctx.repo_path, ctx.repo))
		self._refresh()

	def on_idle(self) -> None:
		if time.monotonic() - self._last_refresh_at >= _IDLE_REFRESH_S:
			self._refresh()

	def status_text(self) -> str:
		return self._input_mode.status_hint(self)

	def draw(self, frame: Frame, area: Rect) -> None:
		ctx = self._ctx
		if ctx is None or area.height <= 0:
			return

		project_label = repo_project_label(ctx.repo_path)
		branch = current_branch_name(ctx.repo)

		show_actions = self._active_tab == "status"
		constraints = [Constraint.length(1), Constraint.length(1)]
		if show_actions:
			constraints.append(Constraint.length(1))
		constraints.append(Constraint.fill(1))
		chunks = Layout().direction(Direction.Vertical).constraints(constraints).split(area)

		try:
			active_index = _TAB_KEYS.index(self._active_tab)
		except ValueError:
			active_index = 0
		render_tab_row(
			frame,
			chunks[0],
			project_label,
			_TABS,
			active_index,
			prefix_focused=self._header_focus == "repo",
		)

		theme = current_theme()
		branch_style = theme.branch
		if self._header_focus == "branch":
			branch_style = focus_style(branch_style)
		branch_label = f"Branch: {branch}"
		if self._active_tab == "tasks":
			branch_label = f"{branch_label} — [Sync tasks]"
		elif self._active_tab == "worktrees":
			branch_label = f"{branch_label} — [Add worktree]"
		frame.render_widget(Paragraph.from_string(branch_label).style(branch_style), chunks[1])

		content = chunks[-1]
		if show_actions:
			if self._action_sets:
				actions_label = f"Actions: {', '.join(self._action_sets)}"
				actions_style = theme.header
			else:
				actions_label = "No Action Groups"
				actions_style = theme.log_date.dim()
			if self._header_focus == "actions":
				actions_style = focus_style(actions_style)
			frame.render_widget(Paragraph.from_string(actions_label).style(actions_style), chunks[2])
		content_highlight = self._header_focus == "changes"
		commit_input = isinstance(self._input_mode, InputContext)
		if self._active_tab == "status":
			self._changes.draw(
				frame,
				content,
				highlight=content_highlight,
				commit_input=commit_input,
			)
		elif self._active_tab == "log":
			self._log.draw(frame, content, highlight=content_highlight)
		elif self._active_tab == "tasks":
			self._tasks.draw(frame, content, highlight=content_highlight)
		else:
			self._worktrees.draw(frame, content, highlight=content_highlight)

	def handle_key(self, key: KeyLike) -> PageResult:
		if is_quit(key) and not isinstance(self._input_mode, InputContext):
			return PageResult(action=PageAction.QUIT)

		dispatch = self._input_mode.dispatch_key(self, key)
		if dispatch.next_mode == "input":
			self._input_mode = input_context()
		elif dispatch.next_mode == "nav":
			self._input_mode = nav_context()
		if dispatch.refresh_log and self._ctx is not None:
			self._log.refresh(self._ctx.repo)
		if dispatch.page_result is not None:
			return dispatch.page_result
		return PageResult()


def home_page() -> Page:
	return HomePage()


def _action_set_names(ctx: PageContext) -> tuple[str, ...]:
	workdir = Path(ctx.repo.workdir) if ctx.repo.workdir else Path(ctx.repo_path)
	if workdir.name == ".git":
		workdir = workdir.parent
	root = find_project_root(workdir)
	if root is None:
		return ()
	try:
		return tuple(action_set.name for action_set in load_action_sets(root))
	except (OSError, ValueError):
		return ()