"""Live elapsed-time indicator for the TUI status bar.

Sits next to the activity indicator and ticks once per second while the agent
is working, showing how long the current request has been running (``2m 16s``).
The timer is driven by the same ``stream_start``/``stream_end`` hooks as the
activity indicator, so it measures the whole turn — all LLM calls, tool calls,
planning, and sub-agent steps. On ``stream_end`` the backend reports the
authoritative ``elapsed_seconds``; the timer syncs to it before freezing so the
final display matches the metadata line written into the chat.
"""

from __future__ import annotations

import time

from rich.text import Text
from textual.timer import Timer
from textual.widgets import Static

from clients.terminal.tui.duration import format_duration
from clients.terminal.tui.themes import get_active_theme

_TICK_SECONDS = 1.0


class ElapsedTimer(Static):
    """A ``2m 16s`` elapsed counter that ticks while started."""

    def __init__(self) -> None:
        super().__init__("")
        self._start_ts: float | None = None
        self._active = False
        self._timer: Timer | None = None

    def start(self) -> None:
        """Begin counting from now and render the initial ``0s``."""
        self._start_ts = time.monotonic()
        self._active = True
        self._render_frame(0.0)
        if self._timer is None:
            self._timer = self.set_interval(_TICK_SECONDS, self._tick)

    def stop(self, final_seconds: float | None = None) -> None:
        """Stop ticking and freeze the display.

        If ``final_seconds`` is given (the backend's authoritative elapsed for
        the turn), sync to it so the frozen value matches the chat metadata.
        Otherwise freeze at the locally-measured elapsed.
        """
        elapsed = final_seconds
        if elapsed is None and self._start_ts is not None:
            elapsed = time.monotonic() - self._start_ts
        self._active = False
        self._start_ts = None
        if self._timer is not None:
            self._timer.stop()
            self._timer = None
        if self.is_mounted:
            self.update(Text(format_duration(elapsed), style=get_active_theme().text_dim.hex))

    def _tick(self) -> None:
        if not self._active or self._start_ts is None:
            return
        self._render_frame(time.monotonic() - self._start_ts)

    def _render_frame(self, elapsed: float) -> None:
        if not self.is_mounted:
            return
        self.update(Text(format_duration(elapsed), style=get_active_theme().text_dim.hex))