"""Rich-based event handler for CLI output."""

from __future__ import annotations

from rich.console import Console
from rich.panel import Panel
from rich.markup import escape as rich_escape

from krim_sdk import EventHandler, Event, EventType


class RichEventHandler(EventHandler):
    """CLI event handler using rich for beautiful terminal output."""

    def __init__(self, verbose: bool = True):
        self.console = Console()
        self.verbose = verbose

    def on_event(self, event: Event) -> None:
        """Handle generic events."""
        if not self.verbose:
            return

        if event.type == EventType.TURN_START:
            turn = event.data.get("turn", 0)
            max_turns = event.data.get("max_turns", 0)
            tokens = event.data.get("tokens", 0)
            self.console.print(f"\n[dim]--- turn {turn}/{max_turns}  ~{tokens:,} tokens ---[/]")

        elif event.type == EventType.DOOM_LOOP:
            count = event.data.get("recovery_count", 0)
            if count == 1:
                self.console.print("[yellow]doom loop detected, nudging recovery[/]")
            else:
                self.console.print("[yellow]doom loop detected (2nd time), forcing stop[/]")

        elif event.type == EventType.MAX_TURNS:
            max_turns = event.data.get("max_turns", 0)
            self.console.print(f"\n[yellow]reached max turns ({max_turns})[/]")

        elif event.type == EventType.MODEL_ERROR:
            error = event.data.get("error", "unknown error")
            self.console.print(f"\n[red]model error: {error}[/]")

    def on_stream(self, text: str) -> None:
        """Called for each streaming text chunk."""
        if self.verbose:
            self.console.print(text, end="", highlight=False)

    def on_tool_start(self, name: str, args: dict) -> None:
        """Called before tool execution."""
        if not self.verbose:
            return

        import json
        icon = {
            "bash": ">>",
            "read": "<<",
            "write": "=>",
            "edit": "<>",
            "grep": "??",
            "glob": "**"
        }.get(name, "::")

        summary = f"[bold cyan]{icon} {name}[/]"
        if name == "bash":
            cmd = args.get("command", "")
            first_line = cmd.split("\n")[0]
            if len(first_line) > 100:
                first_line = first_line[:97] + "..."
            summary += f"  `{first_line}`"
        elif name in ("read", "write", "edit"):
            path = args.get("path", "")
            summary += f"  {path}"
        else:
            summary += f"  {json.dumps(args, ensure_ascii=False)[:80]}"

        self.console.print(summary)

    def on_tool_end(self, name: str, result: str) -> None:
        """Called after tool execution."""
        if not self.verbose:
            return

        # Handle image results - don't print base64
        if result.startswith("<<<IMAGE:"):
            try:
                content = result[len("<<<IMAGE:"):-3]
                media_type = content.split(":", 1)[0]
                self.console.print(Panel(f"[image: {media_type}]", border_style="dim", expand=False, padding=(0, 1)))
                return
            except Exception:
                pass

        lines = result.splitlines()
        preview = "\n".join(lines[:20])
        preview = rich_escape(preview)
        if len(lines) > 20:
            preview += f"\n[dim]... ({len(lines) - 20} more lines)[/]"
        self.console.print(Panel(preview, border_style="dim", expand=False, padding=(0, 1)))

    def on_tool_ask(self, tool_name: str, command: str) -> bool:
        """Called when bash needs user approval."""
        import sys
        if not sys.stdin.isatty():
            return True  # Non-interactive: allow by default

        self.console.print(f"\n[yellow]{tool_name}:[/] [bold]{command}[/]")
        try:
            answer = self.console.input("[yellow]allow? [Y/n] [/]").strip().lower()
            return answer in ("", "y", "yes")
        except (EOFError, KeyboardInterrupt):
            self.console.print()
            return False

    def on_retry(self, attempt: int, max_retries: int, error: Exception, delay: float) -> None:
        """Called before retry."""
        self.console.print(f"[yellow]retry {attempt}/{max_retries} in {delay:.0f}s: {error}[/]")

    def on_compaction(self, before_tokens: int, after_tokens: int) -> None:
        """Called after compaction."""
        if self.verbose:
            self.console.print(f"[dim]compacted: ~{before_tokens:,} -> ~{after_tokens:,} tokens[/]")

    def on_submit(self, summary: str) -> None:
        """Called when agent submits."""
        if self.verbose:
            self.console.print(f"\n[bold green]{summary}[/]")
        else:
            # In quiet mode, show the final response
            self.console.print(summary)
