"""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 (
    CommandContext,
    InputContext,
    InputMode,
    command_context,
    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, CommandContext)):
                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, CommandContext)):
            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 == "command":
            self._input_mode = command_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 ()