"""Tool-specific handlers for CLI display.

This module provides Protocol definitions and handler implementations for
tool-specific formatting. Handlers are frozen dataclasses that can be
composed and tested independently.

Example:
    # Use default Task handler
    handler = TaskRequestHandler()
    output = handler.format({"subagent_type": "Explore", "description": "Search"})

    # Create custom handler
    @dataclass(frozen=True)
    class MyToolHandler:
        def format(self, args: dict[str, Any]) -> str:
            return f"Custom: {args}"
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Protocol, runtime_checkable

# =============================================================================
# Request Handlers - format tool arguments for display
# =============================================================================


@runtime_checkable
class RequestHandler(Protocol):
    """Protocol for tool request handlers.

    Request handlers receive parsed arguments and return formatted output.
    """

    def format(self, args: dict[str, Any]) -> str:
        """Format tool arguments for display.

        Args:
            args: Parsed tool arguments dictionary.

        Returns:
            Formatted string with Rich markup.
        """
        ...


@dataclass(frozen=True)
class TaskRequestHandler:
    """Formats Task (subagent) tool requests.

    Displays subagent spawning with robot emoji, type, name, and description.

    Example output:
        🤖 [Explore] auth-explorer
           Search for authentication patterns
    """

    def format(self, args: dict[str, Any]) -> str:
        """Format Task tool arguments."""
        subagent_type = args.get("subagent_type", "agent")
        description = args.get("description", "")
        name = args.get("name", "")

        # Build header: 🤖 [type] name
        name_part = f" [bold]{name}[/bold]" if name else ""
        header = f"\n[magenta bold]🤖 [{subagent_type}]{name_part}[/magenta bold]"

        # Add description if present
        if description:
            return f"{header}\n[dim]   {description}[/dim]"

        return header


# =============================================================================
# Output Handlers - render cleaned lines for display
# =============================================================================


@runtime_checkable
class OutputHandler(Protocol):
    """Protocol for tool output handlers.

    Output handlers receive cleaned lines (already extracted and filtered)
    and return formatted output. This separation of concerns ensures handlers
    focus only on rendering, not on extraction/filtering.
    """

    def render(self, lines: list[str]) -> str:
        """Render cleaned lines for display.

        Args:
            lines: Cleaned lines (whitespace stripped, empty lines removed).

        Returns:
            Formatted string with Rich markup.
        """
        ...


@dataclass(frozen=True)
class DefaultOutputHandler:
    """Default output handler using green arrow prefix.

    Example output (single line):
        '--> Hello World

    Example output (multi-line):
        '-->
           Line 1
           Line 2
    """

    max_lines: int = 15
    verbose: bool = False

    def render(self, lines: list[str]) -> str:
        """Render lines with green arrow prefix."""
        if not lines:
            return "\n[green dim]  '--> (empty)[/green dim]\n"

        if len(lines) == 1:
            return f"\n[green]  '--> {lines[0]}[/green]\n"

        output_lines = ["\n[green]  '-->[/green]"]

        lines_to_show = lines if self.verbose else lines[: self.max_lines]
        for line in lines_to_show:
            output_lines.append(f"       {line}")

        if not self.verbose and len(lines) > self.max_lines:
            remaining = len(lines) - self.max_lines
            output_lines.append(f"[dim italic]       ... ({remaining} more lines)[/dim italic]")

        return "\n".join(output_lines) + "\n"


@dataclass(frozen=True)
class TaskOutputHandler:
    """Formats Task (subagent) tool output with tree-style prefix.

    Uses └─ prefix to visually connect to the spawning message above.

    Example output (single line):
        └─ Found 5 matching files

    Example output (multi-line):
        └─
           Line 1
           Line 2
    """

    max_lines: int = 15
    verbose: bool = False

    def render(self, lines: list[str]) -> str:
        """Render lines with tree-style prefix."""
        if not lines:
            return "\n[magenta dim]  └─ (no response)[/magenta dim]\n"

        if len(lines) == 1:
            return f"\n[magenta]  └─ {lines[0]}[/magenta]\n"

        output_lines = ["\n[magenta]  └─[/magenta]"]

        lines_to_show = lines if self.verbose else lines[: self.max_lines]
        for line in lines_to_show:
            output_lines.append(f"       {line}")

        if not self.verbose and len(lines) > self.max_lines:
            remaining = len(lines) - self.max_lines
            output_lines.append(f"[dim italic]       ... ({remaining} more lines)[/dim italic]")

        return "\n".join(output_lines) + "\n"


# =============================================================================
# Default handler registry factories
# =============================================================================


def default_request_handlers() -> dict[str, RequestHandler]:
    """Create default request handler registry.

    Returns an empty dict by default - all tools use standard formatting.
    To add custom handlers:

        handlers = default_request_handlers()
        handlers["Task"] = TaskRequestHandler()
    """
    return {}


def default_output_handlers(max_lines: int = 15, verbose: bool = False) -> dict[str, OutputHandler]:
    """Create default output handler registry.

    Returns an empty dict by default - all tools use standard formatting.
    To add custom handlers:

        handlers = default_output_handlers()
        handlers["Task"] = TaskOutputHandler(max_lines=15)
    """
    return {}
