"""pgt TUI application loop."""

from __future__ import annotations

from pathlib import Path

from pyratatui import Frame, Terminal

from pygittools.tui.git_colors import init_tui_color_theme, status_bar_style
from pygittools.tui.keys import set_vim_enabled
from pygittools.tui.pages.home import HomePage, home_page
from pygittools.tui.pages.no_repo import NoRepoPage
from pygittools.tui.repo import try_open_page_context
from pygittools.tui.status_bar import render_status_bar, split_content_status
from pygittools.tui.tabs import init_tab_colors
from pygittools.tui.types import Page, PageAction, PageContext, PageResult


def run_tui(repo_path: Path | None = None) -> int:
    start = (repo_path or Path.cwd()).resolve()
    ctx = try_open_page_context(start)
    initial: Page = home_page() if ctx is not None else NoRepoPage(start)
    stack: list[Page] = [initial]
    set_vim_enabled(False)

    with Terminal() as term:
        term.hide_cursor()
        try:
            init_tui_color_theme(ctx.repo if ctx is not None else None)
            init_tab_colors()

            if ctx is not None:
                stack[0].on_enter(ctx)

            while stack:
                page = stack[-1]

                def ui(frame: Frame, _page: Page = page) -> None:
                    content, status = split_content_status(frame.area)
                    _page.draw(frame, content)
                    render_status_bar(frame, status, _page.status_text(), status_bar_style())

                term.draw(ui)

                try:
                    ev = term.poll_event(timeout_ms=100)
                except KeyboardInterrupt:
                    break
                if ev is None:
                    on_idle = getattr(page, "on_idle", None)
                    if callable(on_idle):
                        on_idle()
                    continue

                result = page.handle_key(ev)
                ctx, stack = _apply_result(stack, ctx, result)
                if result.action == PageAction.QUIT:
                    break
        except KeyboardInterrupt:
            pass
        finally:
            _persist_commit_draft(stack, ctx)

    return 0


def _persist_commit_draft(stack: list[Page], ctx: PageContext | None) -> None:
    if ctx is None:
        return
    for page in reversed(stack):
        if isinstance(page, HomePage):
            page.changes.persist_commit_draft(ctx.repo)
            return


def _apply_result(
    stack: list[Page],
    ctx: PageContext | None,
    result: PageResult,
) -> tuple[PageContext | None, list[Page]]:
    if result.switch_repo is not None:
        _persist_commit_draft(stack, ctx)
        new_ctx = try_open_page_context(result.switch_repo)
        if new_ctx is not None:
            ctx = new_ctx
            init_tui_color_theme(ctx.repo)
            init_tab_colors()

    match result.action:
        case PageAction.REPLACE:
            if result.next_page is None:
                return ctx, stack
            if ctx is not None:
                result.next_page.on_enter(ctx)
            return ctx, [result.next_page]
        case PageAction.PUSH:
            if result.next_page is None:
                return ctx, stack
            if ctx is not None:
                result.next_page.on_enter(ctx)
            return ctx, [*stack, result.next_page]
        case PageAction.POP:
            if len(stack) <= 1:
                return ctx, stack
            stack = stack[:-1]
        case _:
            pass

    if result.switch_repo is not None and ctx is not None and stack:
        stack[-1].on_enter(ctx)
    elif (
        result.repo_changed
        and result.action == PageAction.POP
        and ctx is not None
        and stack
        and isinstance(stack[-1], HomePage)
    ):
        stack[-1].refresh()

    return ctx, stack