"""Status bar widget for ieum."""

from __future__ import annotations

from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, Any

from textual.containers import Horizontal
from textual.css.query import NoMatches
from textual.reactive import reactive
from textual.widgets import Static

from ieum.i18n import t

if TYPE_CHECKING:
    from textual.app import ComposeResult


class StatusBar(Horizontal):
    """Status bar showing mode, auto-approve status, and working directory."""

    DEFAULT_CSS = """
    StatusBar {
        height: 1;
        dock: bottom;
        background: $surface;
        padding: 0 1;
    }

    StatusBar .status-mode {
        width: auto;
        padding: 0 1;
    }

    StatusBar .status-mode.normal {
        display: none;
    }

    StatusBar .status-mode.bash {
        background: #ff1493;
        color: white;
        text-style: bold;
    }

    StatusBar .status-mode.command {
        background: #8b5cf6;
        color: white;
    }

    StatusBar .status-auto-approve {
        width: auto;
        padding: 0 1;
    }

    StatusBar .status-auto-approve.mode-manual {
        background: #f59e0b;
        color: black;
    }

    StatusBar .status-auto-approve.mode-auto {
        background: #10b981;
        color: black;
    }

    StatusBar .status-auto-approve.mode-plan {
        background: #6366f1;
        color: white;
        text-style: bold;
    }

    StatusBar .status-message {
        width: 1fr;
        padding: 0 1;
        color: $text-muted;
    }

    StatusBar .status-message.thinking {
        color: $warning;
    }

    StatusBar .status-cwd {
        width: 1fr;
        text-align: right;
        color: $text-muted;
    }

    StatusBar .status-tokens {
        width: auto;
        padding: 0 1;
        color: $text-muted;
    }

    StatusBar .status-tokens.warning {
        color: #f59e0b;
        text-style: bold;
    }

    StatusBar .status-tokens.critical {
        background: #ef4444;
        color: white;
        text-style: bold;
    }

    StatusBar .status-cost {
        width: auto;
        padding: 0 1;
        color: #10b981;
    }

    StatusBar .status-cost.high {
        color: #f59e0b;
        text-style: bold;
    }

    StatusBar .status-model {
        width: auto;
        padding: 0 1;
        color: $text-muted;
    }

    StatusBar .status-elapsed {
        width: auto;
        padding: 0 1;
        color: $text-muted;
    }
    """

    mode: reactive[str] = reactive("normal", init=False)
    status_message: reactive[str] = reactive("", init=False)
    auto_approve: reactive[bool] = reactive(default=False, init=False)
    approval_mode: reactive[str] = reactive("manual", init=False)
    tokens: reactive[int] = reactive(0, init=False)
    max_tokens: reactive[int] = reactive(0, init=False)  # Context window size
    cost: reactive[float] = reactive(0.0, init=False)  # Session cost in USD
    model_name: reactive[str] = reactive("", init=False)
    elapsed_seconds: reactive[int] = reactive(0, init=False)  # Session elapsed time

    def __init__(self, cwd: str | Path | None = None, **kwargs: Any) -> None:
        """Initialize the status bar.

        Args:
            cwd: Current working directory (kept for API compatibility)
            **kwargs: Additional arguments passed to parent
        """
        super().__init__(**kwargs)
        self._session_start = datetime.now()
        self._elapsed_timer = None

    def compose(self) -> ComposeResult:
        """Compose the status bar layout."""
        yield Static("", classes="status-mode normal", id="mode-indicator")
        yield Static(
            t("status.manual_approval"),
            classes="status-auto-approve mode-manual",
            id="auto-approve-indicator",
        )
        yield Static("", classes="status-message", id="status-message")
        yield Static("", classes="status-elapsed", id="elapsed-display")
        yield Static("", classes="status-cost", id="cost-display")
        yield Static("", classes="status-tokens", id="tokens-display")
        yield Static("", classes="status-model", id="model-display")

    def on_mount(self) -> None:
        """Set reactive values after mount to trigger watchers safely."""
        # Model name will be set by set_model_name() from app.py
        # Don't read from settings here as timing can cause issues
        # Start elapsed time timer (update every second)
        self._elapsed_timer = self.set_interval(1.0, self._update_elapsed_time)

    def on_unmount(self) -> None:
        """Stop the elapsed time timer when unmounted to prevent resource leak."""
        if self._elapsed_timer is not None:
            self._elapsed_timer.stop()
            self._elapsed_timer = None

    def watch_mode(self, mode: str) -> None:
        """Update mode indicator when mode changes."""
        try:
            indicator = self.query_one("#mode-indicator", Static)
        except NoMatches:
            return
        indicator.remove_class("normal", "bash", "command")

        if mode == "bash":
            indicator.update("BASH")
            indicator.add_class("bash")
        elif mode == "command":
            indicator.update("CMD")
            indicator.add_class("command")
        else:
            indicator.update("")
            indicator.add_class("normal")

    def watch_auto_approve(self, new_value: bool) -> None:  # noqa: FBT001
        """Update auto-approve indicator when state changes (legacy compat)."""
        # Delegate to approval_mode for consistent rendering
        if new_value:
            self.approval_mode = "auto"
        elif self.approval_mode == "auto":
            self.approval_mode = "manual"

    def watch_approval_mode(self, new_value: str) -> None:
        """Update approval mode indicator for manual/auto/plan."""
        try:
            indicator = self.query_one("#auto-approve-indicator", Static)
        except NoMatches:
            return
        indicator.remove_class("mode-manual", "mode-auto", "mode-plan")

        if new_value == "auto":
            indicator.update(t("status.auto_approve"))
            indicator.add_class("mode-auto")
        elif new_value == "plan":
            indicator.update("PLAN")
            indicator.add_class("mode-plan")
        else:
            indicator.update(t("status.manual_approval"))
            indicator.add_class("mode-manual")

    def watch_status_message(self, new_value: str) -> None:
        """Update status message display."""
        try:
            msg_widget = self.query_one("#status-message", Static)
        except NoMatches:
            return

        msg_widget.remove_class("thinking")
        if new_value:
            msg_widget.update(new_value)
            if "thinking" in new_value.lower() or "executing" in new_value.lower():
                msg_widget.add_class("thinking")
        else:
            msg_widget.update("")

    def set_mode(self, mode: str) -> None:
        """Set the current input mode.

        Args:
            mode: One of "normal", "bash", or "command"
        """
        self.mode = mode

    def set_auto_approve(self, *, enabled: bool) -> None:
        """Set the auto-approve state.

        Args:
            enabled: Whether auto-approve is enabled
        """
        self.auto_approve = enabled

    def set_approval_mode(self, mode: str) -> None:
        """Set the approval mode indicator.

        Args:
            mode: One of "manual", "auto", or "plan"
        """
        self.approval_mode = mode

    def set_status_message(self, message: str) -> None:
        """Set the status message.

        Args:
            message: Status message to display (empty string to clear)
        """
        self.status_message = message

    def watch_tokens(self, new_value: int) -> None:
        """Update token display when count changes."""
        self._update_tokens_display()

    def watch_max_tokens(self, new_value: int) -> None:
        """Update token display when max tokens changes."""
        self._update_tokens_display()

    def _update_tokens_display(self) -> None:
        """Update the token display with current usage and context limit."""
        try:
            display = self.query_one("#tokens-display", Static)
        except NoMatches:
            return

        # Remove existing warning classes
        display.remove_class("warning", "critical")

        if self.tokens > 0:
            # Format current tokens
            if self.tokens >= 1000:
                current = f"{self.tokens / 1000:.1f}K"
            else:
                current = str(self.tokens)

            # If max_tokens is available, show usage percentage with warnings
            if self.max_tokens > 0:
                if self.max_tokens >= 1000:
                    max_str = f"{self.max_tokens / 1000:.0f}K"
                else:
                    max_str = str(self.max_tokens)
                pct = (self.tokens / self.max_tokens) * 100

                # Add warning/critical styling based on usage
                if pct >= 90:
                    display.add_class("critical")
                    display.update(f"⚠ {current}/{max_str} ({pct:.0f}%)")
                elif pct >= 75:
                    display.add_class("warning")
                    display.update(f"{current}/{max_str} ({pct:.0f}%)")
                else:
                    display.update(f"{current}/{max_str} ({pct:.0f}%)")
            else:
                display.update(f"{current} tokens")
        else:
            display.update("")

    def set_tokens(self, count: int) -> None:
        """Set the token count.

        Args:
            count: Current context token count
        """
        self.tokens = count

    def set_max_tokens(self, count: int) -> None:
        """Set the maximum context window size.

        Args:
            count: Maximum context tokens (from model profile)
        """
        self.max_tokens = count

    def hide_tokens(self) -> None:
        """Hide the token display (e.g., during streaming)."""
        self.query_one("#tokens-display", Static).update("")

    def watch_cost(self, new_value: float) -> None:
        """Update cost display when cost changes."""
        try:
            display = self.query_one("#cost-display", Static)
        except NoMatches:
            return

        display.remove_class("high")
        if new_value > 0:
            if new_value >= 1.0:
                display.add_class("high")
                display.update(f"${new_value:.2f}")
            elif new_value >= 0.01:
                display.update(f"${new_value:.4f}")
            else:
                display.update(f"${new_value:.4f}")
        else:
            display.update("")

    def set_cost(self, amount: float) -> None:
        """Set the session cost.

        Args:
            amount: Cost in USD.
        """
        self.cost = amount

    def watch_model_name(self, new_value: str) -> None:
        """Update model display when model changes."""
        try:
            display = self.query_one("#model-display", Static)
        except NoMatches:
            return
        display.update(new_value)

    def set_model_name(self, name: str) -> None:
        """Set the model name display.

        Args:
            name: Model name to display (e.g., "ollama/llama3")
        """
        self.model_name = name

    def _update_elapsed_time(self) -> None:
        """Update elapsed time (called by timer)."""
        elapsed = datetime.now() - self._session_start
        self.elapsed_seconds = int(elapsed.total_seconds())

    def watch_elapsed_seconds(self, new_value: int) -> None:
        """Update elapsed time display."""
        try:
            display = self.query_one("#elapsed-display", Static)
        except NoMatches:
            return

        # Format as HH:MM:SS or MM:SS
        hours, remainder = divmod(new_value, 3600)
        minutes, seconds = divmod(remainder, 60)
        if hours > 0:
            display.update(f"{hours}:{minutes:02d}:{seconds:02d}")
        else:
            display.update(f"{minutes}:{seconds:02d}")

    def reset_elapsed_time(self) -> None:
        """Reset the session start time (e.g., when starting a new conversation)."""
        self._session_start = datetime.now()
        self.elapsed_seconds = 0
