"""
Tool Context Type.

Represents available tools and recent tool execution results.
"""

from dataclasses import dataclass, field
from datetime import UTC, datetime
from enum import Enum
from typing import Any

from .base import BaseContext, ContextPriority, ContextType


class ToolResultStatus(str, Enum):
    """Status of a tool execution result."""

    SUCCESS = "success"
    ERROR = "error"
    TIMEOUT = "timeout"
    CANCELLED = "cancelled"


@dataclass(eq=False)
class ToolContext(BaseContext):
    """
    Context for tools and tool execution results.

    Tool context includes:
    - Tool descriptions and parameters
    - Recent tool execution results
    - Tool availability information

    This helps the LLM understand what tools are available
    and what results previous tool calls produced.
    """

    # Tool-specific fields
    tool_name: str = field(default="")
    tool_description: str = field(default="")
    is_result: bool = field(default=False)
    result_status: ToolResultStatus | None = field(default=None)
    execution_time_ms: float | None = field(default=None)
    parameters: dict[str, Any] = field(default_factory=dict)
    server_name: str | None = field(default=None)

    def get_type(self) -> ContextType:
        """Return TOOL context type."""
        return ContextType.TOOL

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary with tool-specific fields."""
        base = super().to_dict()
        base.update(
            {
                "tool_name": self.tool_name,
                "tool_description": self.tool_description,
                "is_result": self.is_result,
                "result_status": self.result_status.value
                if self.result_status
                else None,
                "execution_time_ms": self.execution_time_ms,
                "parameters": self.parameters,
                "server_name": self.server_name,
            }
        )
        return base

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "ToolContext":
        """Create ToolContext from dictionary."""
        result_status = data.get("result_status")
        if isinstance(result_status, str):
            result_status = ToolResultStatus(result_status)

        return cls(
            id=data.get("id", ""),
            content=data["content"],
            source=data.get("source", "tool"),
            timestamp=datetime.fromisoformat(data["timestamp"])
            if isinstance(data.get("timestamp"), str)
            else data.get("timestamp", datetime.now(UTC)),
            priority=data.get("priority", ContextPriority.NORMAL.value),
            metadata=data.get("metadata", {}),
            tool_name=data.get("tool_name", ""),
            tool_description=data.get("tool_description", ""),
            is_result=data.get("is_result", False),
            result_status=result_status,
            execution_time_ms=data.get("execution_time_ms"),
            parameters=data.get("parameters", {}),
            server_name=data.get("server_name"),
        )

    @classmethod
    def from_tool_definition(
        cls,
        name: str,
        description: str,
        parameters: dict[str, Any] | None = None,
        server_name: str | None = None,
    ) -> "ToolContext":
        """
        Create a ToolContext from a tool definition.

        Args:
            name: Tool name
            description: Tool description
            parameters: Tool parameter schema
            server_name: MCP server name

        Returns:
            ToolContext instance
        """
        # Format content as tool documentation
        content_parts = [f"Tool: {name}", "", description]

        if parameters:
            content_parts.append("")
            content_parts.append("Parameters:")
            for param_name, param_info in parameters.items():
                param_type = param_info.get("type", "any")
                param_desc = param_info.get("description", "")
                required = param_info.get("required", False)
                req_marker = " (required)" if required else ""
                content_parts.append(f"  - {param_name}: {param_type}{req_marker}")
                if param_desc:
                    content_parts.append(f"    {param_desc}")

        return cls(
            content="\n".join(content_parts),
            source=f"tool:{server_name}:{name}" if server_name else f"tool:{name}",
            tool_name=name,
            tool_description=description,
            is_result=False,
            parameters=parameters or {},
            server_name=server_name,
            priority=ContextPriority.LOW.value,
        )

    @classmethod
    def from_tool_result(
        cls,
        tool_name: str,
        result: Any,
        status: ToolResultStatus = ToolResultStatus.SUCCESS,
        execution_time_ms: float | None = None,
        parameters: dict[str, Any] | None = None,
        server_name: str | None = None,
    ) -> "ToolContext":
        """
        Create a ToolContext from a tool execution result.

        Args:
            tool_name: Name of the tool that was executed
            result: Result content (will be converted to string)
            status: Execution status
            execution_time_ms: Execution time in milliseconds
            parameters: Parameters that were passed to the tool
            server_name: MCP server name

        Returns:
            ToolContext instance
        """
        # Convert result to string content
        if isinstance(result, str):
            content = result
        elif isinstance(result, dict):
            import json

            try:
                content = json.dumps(result, indent=2)
            except (TypeError, ValueError):
                content = str(result)
        else:
            content = str(result)

        return cls(
            content=content,
            source=f"tool_result:{server_name}:{tool_name}"
            if server_name
            else f"tool_result:{tool_name}",
            tool_name=tool_name,
            is_result=True,
            result_status=status,
            execution_time_ms=execution_time_ms,
            parameters=parameters or {},
            server_name=server_name,
            priority=ContextPriority.HIGH.value,  # Recent results are high priority
        )

    def is_successful(self) -> bool:
        """Check if this is a successful tool result."""
        return self.is_result and self.result_status == ToolResultStatus.SUCCESS

    def is_error(self) -> bool:
        """Check if this is an error result."""
        return self.is_result and self.result_status == ToolResultStatus.ERROR

    def format_for_prompt(self) -> str:
        """
        Format tool context for inclusion in prompt.

        Returns:
            Formatted tool string
        """
        if self.is_result:
            status_str = self.result_status.value if self.result_status else "unknown"
            header = f"Tool Result ({self.tool_name}, {status_str}):"
            return f"{header}\n{self.content}"
        else:
            return self.content
