"""
Response Renderer - Beautiful terminal output with Rich

Provides formatted output for the REPL:
- Markdown rendering for responses
- Streaming token output
- Tool execution results
- Status indicators and progress

Examples:
    renderer = ResponseRenderer(console)

    # Render markdown response
    renderer.render_response("# Hello\nThis is **bold**")

    # Stream tokens
    for token in tokens:
        renderer.render_streaming(token)
    renderer.finish_streaming()

    # Show tool output
    renderer.render_tool_output(ToolResult(success=True, output="Done"))
"""

from dataclasses import dataclass
from typing import Any, Optional

from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.syntax import Syntax
from rich.table import Table
from rich.text import Text


@dataclass
class StatusStyle:
    """Styles for different status types"""

    info: str = "cyan"
    success: str = "green"
    warning: str = "yellow"
    error: str = "red"
    processing: str = "blue"


class ResponseRenderer:
    """
    Render responses with Rich formatting

    Provides beautiful terminal output for REPL responses,
    tool outputs, and status messages.

    Example:
        renderer = ResponseRenderer()

        # Render response
        renderer.render_response("Here's the fix...")

        # Show status
        renderer.render_status("Processing...", "info")

        # Display tool output
        renderer.render_tool_output(result)
    """

    def __init__(
        self,
        console: Optional[Console] = None,
        stream_enabled: bool = True,
        styles: Optional[StatusStyle] = None,
    ):
        """
        Initialize renderer

        Args:
            console: Rich console instance
            stream_enabled: Enable streaming output
            styles: Custom status styles
        """
        self.console = console or Console()
        self.stream_enabled = stream_enabled
        self.styles = styles or StatusStyle()
        self._stream_buffer: str = ""  # Use string accumulator instead of list
        self._live: Optional[Live] = None

    def render_response(
        self,
        response: str,
        title: str = "groknroll",
        border_style: str = "cyan",
    ) -> None:
        """
        Render a response with Markdown formatting

        Args:
            response: Response text (Markdown supported)
            title: Panel title
            border_style: Rich border style
        """
        content = Markdown(response)
        panel = Panel(
            content,
            title=f"[bold {border_style}]{title}[/bold {border_style}]",
            border_style=border_style,
            padding=(1, 2),
        )
        self.console.print()
        self.console.print(panel)
        self.console.print()

    def render_streaming(self, token: str) -> None:
        """
        Render a streaming token

        Accumulates tokens and updates the live display.

        Args:
            token: Token to display
        """
        if not self.stream_enabled:
            return

        self._stream_buffer += token  # O(1) amortized string concatenation

        if self._live is None:
            self._live = Live(
                Text(self._stream_buffer),
                console=self.console,
                refresh_per_second=10,
                transient=False,
            )
            self._live.start()
        else:
            self._live.update(Text(self._stream_buffer))

    def finish_streaming(self, render_final: bool = True) -> str:
        """
        Finish streaming and optionally render final response

        Args:
            render_final: Render the complete response with formatting

        Returns:
            Complete response text
        """
        if self._live is not None:
            self._live.stop()
            self._live = None

        response = self._stream_buffer
        self._stream_buffer = ""  # Reset accumulator

        if render_final and response:
            self.console.print()  # Clear streaming line
            self.render_response(response)

        return response

    def render_tool_output(
        self,
        tool_name: str,
        success: bool,
        output: Any,
        show_name: bool = True,
    ) -> None:
        """
        Render tool execution output

        Args:
            tool_name: Name of the executed tool
            success: Whether execution succeeded
            output: Output from the tool
            show_name: Show tool name in title
        """
        border_style = self.styles.success if success else self.styles.error
        status_icon = "[green]OK[/green]" if success else "[red]ERROR[/red]"

        title = f"{tool_name}" if show_name else "Tool Output"
        if not success:
            title = f"{title} ({status_icon})"

        # Format output
        if isinstance(output, dict):
            content = self._format_dict(output)
        elif isinstance(output, list):
            content = self._format_list(output)
        elif isinstance(output, str) and len(output) > 0:
            # Check if it looks like code
            if output.strip().startswith(("{", "[", "def ", "class ", "import ")):
                content = Syntax(output, "python", theme="monokai", line_numbers=True)
            else:
                content = Text(output)
        else:
            content = Text(str(output) if output else "[dim]No output[/dim]")

        panel = Panel(
            content,
            title=f"[bold]{title}[/bold]",
            border_style=border_style,
        )
        self.console.print(panel)

    def render_status(
        self,
        message: str,
        status_type: str = "info",
        icon: Optional[str] = None,
    ) -> None:
        """
        Render a status message

        Args:
            message: Status message
            status_type: Type (info, success, warning, error, processing)
            icon: Optional icon override
        """
        style = getattr(self.styles, status_type, self.styles.info)

        default_icons = {
            "info": "ℹ️",
            "success": "[green]✓[/green]",
            "warning": "[yellow]⚠[/yellow]",
            "error": "[red]✗[/red]",
            "processing": "[blue]⟳[/blue]",
        }

        icon = icon or default_icons.get(status_type, "")
        self.console.print(f"{icon} [{style}]{message}[/{style}]")

    def render_error(self, error: str, details: Optional[str] = None) -> None:
        """
        Render an error message

        Args:
            error: Error message
            details: Optional error details
        """
        content_parts = [f"[bold red]{error}[/bold red]"]
        if details:
            content_parts.append(f"\n[dim]{details}[/dim]")

        panel = Panel(
            "\n".join(content_parts),
            title="[bold red]Error[/bold red]",
            border_style="red",
        )
        self.console.print(panel)

    def render_welcome(
        self,
        version: str,
        agent: str = "build",
        custom_message: Optional[str] = None,
    ) -> None:
        """
        Render welcome banner

        Args:
            version: Application version
            agent: Current agent name
            custom_message: Custom welcome message
        """
        message = custom_message or (
            "Type your task and press Enter.\n"
            "Commands: [cyan]/help[/cyan], [cyan]/agent[/cyan], "
            "[cyan]/save[/cyan], [cyan]/quit[/cyan]\n"
            "Shell: [cyan]!command[/cyan] | Files: [cyan]@filename[/cyan]"
        )

        content = (
            f"[bold cyan]groknroll[/bold cyan] v{version}\n[dim]Agent: {agent}[/dim]\n\n{message}"
        )

        panel = Panel.fit(
            content,
            border_style="cyan",
            padding=(1, 2),
        )
        self.console.print()
        self.console.print(panel)
        self.console.print()

    def render_goodbye(self) -> None:
        """Render goodbye message"""
        self.console.print("\n[dim]Goodbye![/dim]\n")

    def render_help(self, commands: list[dict]) -> None:
        """
        Render help information

        Args:
            commands: List of command dicts with name, description, usage
        """
        table = Table(title="Available Commands", show_header=True)
        table.add_column("Command", style="cyan")
        table.add_column("Description")
        table.add_column("Usage", style="dim")

        for cmd in commands:
            table.add_row(
                cmd.get("name", ""),
                cmd.get("description", ""),
                cmd.get("usage", ""),
            )

        panel = Panel(
            table,
            title="[bold]Help[/bold]",
            border_style="blue",
        )
        self.console.print(panel)

    def render_code(
        self,
        code: str,
        language: str = "python",
        title: Optional[str] = None,
    ) -> None:
        """
        Render syntax-highlighted code

        Args:
            code: Code to display
            language: Programming language
            title: Optional panel title
        """
        syntax = Syntax(code, language, theme="monokai", line_numbers=True)
        if title:
            panel = Panel(syntax, title=title, border_style="dim")
            self.console.print(panel)
        else:
            self.console.print(syntax)

    def render_table(
        self,
        headers: list[str],
        rows: list[list[str]],
        title: Optional[str] = None,
    ) -> None:
        """
        Render a table

        Args:
            headers: Column headers
            rows: Table rows
            title: Optional table title
        """
        table = Table(title=title, show_header=True)
        for header in headers:
            table.add_column(header)
        for row in rows:
            table.add_row(*row)
        self.console.print(table)

    def show_progress(self, description: str = "Working...") -> Progress:
        """
        Create a progress spinner

        Args:
            description: Progress description

        Returns:
            Progress context manager
        """
        return Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            console=self.console,
            transient=True,
        )

    def clear(self) -> None:
        """Clear the terminal"""
        self.console.clear()

    def print_prompt(self, prompt: str = "> ", style: str = "bold cyan") -> None:
        """
        Print the input prompt

        Args:
            prompt: Prompt string
            style: Rich style
        """
        self.console.print(f"[{style}]{prompt}[/{style}]", end="")

    def _format_dict(self, data: dict) -> Table:
        """Format dictionary as table"""
        table = Table(show_header=False, box=None)
        table.add_column("Key", style="cyan")
        table.add_column("Value")

        for key, value in data.items():
            table.add_row(str(key), str(value))

        return table

    def _format_list(self, data: list) -> Text:
        """Format list as bullet points"""
        lines = []
        for item in data:
            lines.append(f"  - {item}")
        return Text("\n".join(lines))


def create_renderer(
    console: Optional[Console] = None,
    stream_enabled: bool = True,
) -> ResponseRenderer:
    """
    Create a response renderer (convenience function)

    Args:
        console: Optional Rich console
        stream_enabled: Enable streaming

    Returns:
        Configured ResponseRenderer
    """
    return ResponseRenderer(console=console, stream_enabled=stream_enabled)
