"""Rich display utilities for CLI output."""

import asyncio
import time
from contextlib import contextmanager
from typing import Any, Generator

from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
from rich.spinner import Spinner
from rich.table import Table

console = Console()
error_console = Console(stderr=True)


def print_markdown(text: str) -> None:
    """Render markdown to console."""
    console.print(Markdown(text))


def print_error(msg: str) -> None:
    """Print error message in red to stderr."""
    error_console.print(f"[red]{msg}[/red]")


def print_tool_call(name: str, result_preview: str, tool_input: dict | None = None) -> None:
    """Print tool call with context-aware summary and output preview."""
    if tool_input is None:
        truncated = result_preview[:200] if len(result_preview) > 200 else result_preview
        console.print(f"  [dim]\\[{name}][/dim] {truncated}")
        return

    from fliiq.cli.tui.widgets import _format_tool_detail, _format_tool_summary

    summary = _format_tool_summary(name, tool_input, result_preview)
    console.print(f"  [dim]{summary}[/dim]")

    detail = _format_tool_detail(name, tool_input, result_preview)
    detail_lines = [line for line in detail.splitlines() if line.strip()] if detail else []
    if detail_lines:
        console.print(f"    [dim]\u23bf  {detail_lines[0][:120]}[/dim]")
        for dl in detail_lines[1:3]:
            console.print(f"    [dim]   {dl[:120]}[/dim]")
        remaining = len(detail_lines) - 3
        if remaining > 0:
            console.print(f"    [dim]   ... +{remaining} more lines[/dim]")


def print_mode(mode: str) -> None:
    """Print mode indicator with color coding."""
    colors = {
        "autonomous": "green",
        "supervised": "yellow",
        "plan": "red",
    }
    color = colors.get(mode, "white")
    console.print(f"[{color}]Mode: {mode}[/{color}]")


@contextmanager
def create_spinner(text: str) -> Generator[Live, None, None]:
    """Return Rich Live spinner context manager."""
    spinner = Spinner("dots", text=text)
    with Live(spinner, console=console, refresh_per_second=10) as live:
        yield live


def prompt_tool_approval(name: str, tool_input: dict[str, Any]) -> str:
    """Supervised mode: show tool and params, return 'y', 'n', or 'a'."""
    console.print(f"\n[yellow]Tool call:[/yellow] [bold]{name}[/bold]")
    for key, value in tool_input.items():
        val_str = str(value)
        if len(val_str) > 100:
            val_str = val_str[:100] + "..."
        console.print(f"  [dim]{key}:[/dim] {val_str}")

    while True:
        response = console.input("[yellow]Approve? \\[y]es / \\[n]o / \\[a]pprove all: [/yellow]").strip().lower()
        if response in ("y", "yes"):
            return "y"
        if response in ("n", "no"):
            return "n"
        if response in ("a", "all"):
            return "a"
        console.print("[dim]Enter y, n, or a[/dim]")


def print_table(headers: list[str], rows: list[list[str]], title: str | None = None) -> None:
    """Print a Rich table."""
    table = Table(title=title)
    for header in headers:
        table.add_column(header)
    for row in rows:
        table.add_row(*row)
    console.print(table)


def print_status(mode: str, message_count: int, iteration_total: int) -> None:
    """Print session status info."""
    colors = {"autonomous": "green", "supervised": "yellow", "plan": "red"}
    color = colors.get(mode, "white")
    console.print(f"[{color}]Mode:[/{color}] {mode}")
    console.print(f"[dim]Messages:[/dim] {message_count}")
    console.print(f"[dim]Iterations:[/dim] {iteration_total}")


class ThinkingIndicator:
    """Async thinking indicator with spinner and elapsed time."""

    def __init__(self, con: Console | None = None):
        self._console = con or console
        self._start: float = 0
        self._live: Live | None = None
        self._task: asyncio.Task | None = None

    async def start(self):
        self._start = time.time()
        spinner = Spinner("dots", text="Thinking...")
        self._live = Live(spinner, console=self._console, refresh_per_second=10)
        self._live.start()
        self._task = asyncio.create_task(self._update_elapsed())

    async def stop(self):
        if self._task:
            self._task.cancel()
            try:
                await self._task
            except asyncio.CancelledError:
                pass
        if self._live:
            self._live.stop()
            self._live = None
        elapsed = int(time.time() - self._start)
        self._console.print(f"  [dim]({elapsed}s)[/dim]")

    def pause(self):
        """Pause spinner for user input (sync — safe from tool handlers)."""
        if self._live:
            self._live.stop()

    def resume(self):
        """Resume spinner after user input (sync)."""
        if self._live:
            self._live.start()

    async def _update_elapsed(self):
        while True:
            await asyncio.sleep(1)
            elapsed = int(time.time() - self._start)
            if self._live:
                self._live.update(
                    Spinner("dots", text=f"Thinking... {elapsed}s")
                )
