"""Tool use display widget for visualizing SDK tool invocations."""

from dataclasses import dataclass, field
from typing import Any

from rich.json import JSON
from rich.panel import Panel
from rich.text import Text
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Vertical
from textual.widgets import Collapsible, Static


@dataclass
class ToolInvocation:
    """Represents a single tool invocation."""

    name: str
    tool_id: str = ""
    inputs: dict[str, Any] = field(default_factory=dict)
    output: str | None = None
    status: str = "pending"  # pending, running, success, error
    error: str | None = None
    duration_ms: int | None = None

    @property
    def is_complete(self) -> bool:
        """Whether the tool has finished executing."""
        return self.status in ("success", "error")

    @property
    def status_icon(self) -> str:
        """Icon representing current status."""
        return {
            "pending": "⏳",
            "running": "⚙️",
            "success": "✓",
            "error": "✗",
        }.get(self.status, "?")


class ToolUseBlock(Vertical):
    """Collapsible widget for displaying a tool invocation.

    Shows tool name and status in header; inputs and output in collapsible body.

    Usage:
        invocation = ToolInvocation(name="Read", inputs={"file": "foo.py"})
        block = ToolUseBlock(invocation)
        # Later, update with output:
        block.set_output("file contents here...")
        block.set_status("success")
    """

    DEFAULT_CSS = """
    ToolUseBlock {
        height: auto;
        margin: 0 0 1 0;
    }

    ToolUseBlock Collapsible {
        padding: 0;
    }

    ToolUseBlock .tool-header {
        background: $surface;
        padding: 0 1;
    }

    ToolUseBlock .tool-header.pending {
        color: $warning;
    }

    ToolUseBlock .tool-header.running {
        color: $primary;
    }

    ToolUseBlock .tool-header.success {
        color: $success;
    }

    ToolUseBlock .tool-header.error {
        color: $error;
    }

    ToolUseBlock .tool-inputs {
        padding: 0 1;
        color: $text-muted;
    }

    ToolUseBlock .tool-output {
        padding: 0 1;
        background: $surface-darken-1;
        max-height: 20;
        overflow-y: auto;
    }

    ToolUseBlock .tool-error {
        padding: 0 1;
        color: $error;
    }
    """

    BINDINGS = [
        Binding("enter", "toggle", "Expand/Collapse", show=False),
    ]

    def __init__(
        self,
        invocation: ToolInvocation,
        name: str | None = None,
        id: str | None = None,
        classes: str | None = None,
    ) -> None:
        super().__init__(name=name, id=id, classes=classes)
        self._invocation = invocation
        self._collapsed = True

    def compose(self) -> ComposeResult:
        """Compose the tool use block."""
        inv = self._invocation
        header_text = f"{inv.status_icon} {inv.name}"
        if inv.duration_ms is not None:
            header_text += f" ({inv.duration_ms}ms)"

        with Collapsible(title=header_text, collapsed=self._collapsed):
            # Inputs section
            if inv.inputs:
                yield Static(
                    self._format_inputs(inv.inputs),
                    classes="tool-inputs",
                )

            # Output or error section
            if inv.error:
                yield Static(f"Error: {inv.error}", classes="tool-error")
            elif inv.output:
                yield Static(
                    self._format_output(inv.output),
                    classes="tool-output",
                )

    def _format_inputs(self, inputs: dict[str, Any]) -> Text:
        """Format tool inputs for display."""
        text = Text()
        text.append("Inputs:\n", style="bold")
        for key, value in inputs.items():
            # Truncate long values
            str_value = str(value)
            if len(str_value) > 100:
                str_value = str_value[:100] + "..."
            text.append(f"  {key}: ", style="dim")
            text.append(f"{str_value}\n")
        return text

    def _format_output(self, output: str) -> str:
        """Format tool output for display."""
        # Truncate very long outputs
        max_lines = 50
        lines = output.split("\n")
        if len(lines) > max_lines:
            return "\n".join(lines[:max_lines]) + f"\n... ({len(lines) - max_lines} more lines)"
        return output

    def set_status(self, status: str) -> None:
        """Update the tool status."""
        self._invocation.status = status
        self.refresh()

    def set_output(self, output: str) -> None:
        """Set the tool output."""
        self._invocation.output = output
        self.refresh()

    def set_error(self, error: str) -> None:
        """Set error message and status."""
        self._invocation.error = error
        self._invocation.status = "error"
        self.refresh()

    def set_duration(self, duration_ms: int) -> None:
        """Set execution duration."""
        self._invocation.duration_ms = duration_ms
        self.refresh()

    def action_toggle(self) -> None:
        """Toggle collapsed state."""
        self._collapsed = not self._collapsed
        collapsible = self.query_one(Collapsible)
        collapsible.collapsed = self._collapsed


class ToolUseDisplay(Vertical):
    """Container for multiple tool use blocks.

    Manages a list of tool invocations with auto-scroll and status tracking.

    Interface for ChatPanel integration:
        add_tool(name, inputs) -> ToolUseBlock
        update_tool(tool_id, output=..., status=..., error=...)
        get_tool(tool_id) -> ToolUseBlock | None
        clear()
    """

    DEFAULT_CSS = """
    ToolUseDisplay {
        height: auto;
        max-height: 30;
        overflow-y: auto;
        padding: 0 1;
    }
    """

    def __init__(
        self,
        name: str | None = None,
        id: str | None = None,
        classes: str | None = None,
    ) -> None:
        super().__init__(name=name, id=id, classes=classes)
        self._tools: dict[str, ToolUseBlock] = {}
        self._counter = 0

    def add_tool(
        self,
        tool_name: str,
        inputs: dict[str, Any] | None = None,
        tool_id: str | None = None,
    ) -> ToolUseBlock:
        """Add a new tool invocation.

        Args:
            tool_name: Name of the tool being invoked.
            inputs: Tool input parameters.
            tool_id: Optional ID for the tool (auto-generated if not provided).

        Returns:
            The created ToolUseBlock widget.
        """
        if tool_id is None:
            tool_id = f"tool-{self._counter}"
            self._counter += 1

        invocation = ToolInvocation(
            name=tool_name,
            tool_id=tool_id,
            inputs=inputs or {},
            status="running",
        )

        block = ToolUseBlock(invocation, id=tool_id)
        self._tools[tool_id] = block
        self.mount(block)
        self.scroll_end()

        return block

    def update_tool(
        self,
        tool_id: str,
        output: str | None = None,
        status: str | None = None,
        error: str | None = None,
        duration_ms: int | None = None,
    ) -> None:
        """Update an existing tool invocation.

        Args:
            tool_id: ID of the tool to update.
            output: Tool output to display.
            status: New status (pending/running/success/error).
            error: Error message if failed.
            duration_ms: Execution duration in milliseconds.
        """
        block = self._tools.get(tool_id)
        if block is None:
            return

        if output is not None:
            block.set_output(output)
        if status is not None:
            block.set_status(status)
        if error is not None:
            block.set_error(error)
        if duration_ms is not None:
            block.set_duration(duration_ms)

    def get_tool(self, tool_id: str) -> ToolUseBlock | None:
        """Get a tool block by ID."""
        return self._tools.get(tool_id)

    def clear(self) -> None:
        """Remove all tool blocks."""
        for block in self._tools.values():
            block.remove()
        self._tools.clear()
        self._counter = 0
