"""
Tool Base Classes — Compatible with Backend

These classes mirror the backend's agent.tools.base interface so that
backend tool implementations can be imported and used directly.
No Django dependency — works standalone.
"""

from dataclasses import dataclass, field
from typing import Dict, Any, Optional, List
from enum import Enum
from abc import ABC, abstractmethod


class ToolPermission(Enum):
    """Permission levels for tools — matches backend."""
    READ = "read"
    WRITE = "write"
    EXECUTE = "execute"
    NETWORK = "network"
    ADMIN = "admin"
    SYSTEM = "system"


@dataclass
class ToolParameter:
    """Tool parameter definition — matches backend signature."""
    name: str
    type: str  # "string", "int", "bool", "path", "choice", "list", "dict"
    required: bool = True
    default: Any = None
    description: str = ""
    choices: Optional[List[str]] = None
    enum: Optional[List[str]] = None

    def validate(self, value: Any) -> bool:
        """Validate parameter value."""
        if self.required and value is None:
            return False
        if value is None:
            return True
        if self.type == "int":
            try:
                int(value)
                return True
            except (ValueError, TypeError):
                return False
        elif self.type == "bool":
            return isinstance(value, bool) or value in ["true", "false", "True", "False", True, False]
        elif self.type == "choice":
            return value in self.choices if self.choices else True
        elif self.type == "path":
            return isinstance(value, str) and len(value) > 0
        elif self.type == "list":
            return isinstance(value, list)
        elif self.type == "dict":
            return isinstance(value, dict)
        return True


@dataclass
class ToolMetadata:
    """Tool identification and documentation — matches backend."""
    name: str
    category: str = "general"
    description: str = ""
    parameters: List[ToolParameter] = field(default_factory=list)
    permissions: List[ToolPermission] = field(default_factory=list)
    examples: List[str] = field(default_factory=list)
    version: str = "1.0"
    enabled: bool = True
    tags: List[str] = field(default_factory=list)
    verification_status: str = "pending"
    last_verified_at: Optional[str] = None
    risk_tier: str = "low"
    params_schema: Optional[Dict[str, Any]] = None
    output_schema: Optional[Dict[str, Any]] = None
    requires_auth: bool = False
    auth_schema: Optional[Dict[str, Any]] = None
    tool_version: str = "1.0.0"
    timeout: int = 300


@dataclass
class ToolExecutionContext:
    """
    Runtime context — compatible with backend's ToolExecutionContext.

    Backend tools access: workspace_path, metadata (for cwd), permissions.
    Workspace tools access: workspace_path, agent_id, agent_name, request_id.
    This class supports both usage patterns.
    """
    # Backend-compatible fields
    repository: Any = None  # Always None in workspace agent
    user: Any = None        # Always None in workspace agent
    session_id: str = ""
    workspace_path: str = "/workspace"
    permissions: List[ToolPermission] = field(default_factory=lambda: [
        ToolPermission.READ, ToolPermission.WRITE,
        ToolPermission.EXECUTE, ToolPermission.NETWORK,
    ])
    trace: List[Dict[str, Any]] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    agent_profile: Any = None  # Always None in workspace agent

    # Workspace-agent specific fields
    agent_id: str = ""
    agent_name: str = ""
    request_id: str = ""
    user_id: str = ""
    cwd: str = ""

    def get_cwd(self) -> str:
        """Get current working directory, defaulting to workspace_path."""
        return self.cwd or self.metadata.get("cwd", self.workspace_path)


@dataclass
class ToolResult:
    """Result of a tool execution — matches backend."""
    success: bool
    output: str = ""
    error: Optional[str] = None
    metadata: Dict[str, Any] = field(default_factory=dict)
    citations: List[str] = field(default_factory=list)
    base64_image: Optional[str] = None

    @staticmethod
    def ok(output: str, **metadata) -> "ToolResult":
        return ToolResult(success=True, output=output, metadata=metadata)

    @staticmethod
    def fail(error: str, **metadata) -> "ToolResult":
        return ToolResult(success=False, error=error, metadata=metadata)


class BaseTool(ABC):
    """Abstract base for all tools — matches backend."""

    def __init__(self):
        self._metadata: Optional[ToolMetadata] = None

    @abstractmethod
    def get_metadata(self) -> ToolMetadata:
        """Return tool metadata."""
        ...

    @abstractmethod
    def execute(self, params: Dict[str, Any], context: ToolExecutionContext) -> ToolResult:
        """Execute the tool with given parameters and context."""
        ...

    @property
    def name(self) -> str:
        return self.get_metadata().name

    @property
    def permissions(self) -> List[ToolPermission]:
        return self.get_metadata().permissions

    def validate_parameters(self, params: Dict[str, Any]) -> tuple:
        """Validate parameters against metadata."""
        metadata = self.get_metadata()
        for param_def in metadata.parameters:
            if param_def.required and param_def.name not in params:
                return False, f"Missing required parameter: {param_def.name}"
            value = params.get(param_def.name)
            if value is not None and not param_def.validate(value):
                return False, f"Invalid value for {param_def.name}: {value}"
        return True, None

    def check_permissions(self, context: ToolExecutionContext) -> bool:
        """Check if context has required permissions."""
        required = self.get_metadata().permissions
        return all(perm in context.permissions for perm in required)
