"""
Farnsworth Agent Tools - MCP Tool Implementations for Agent Operations

Provides agent swarm capabilities:
- Task delegation to specialists
- Agent status monitoring
- Multi-agent task coordination
"""

from dataclasses import dataclass
from typing import Optional, Any
from datetime import datetime

from loguru import logger


@dataclass
class AgentToolResult:
    """Result from an agent tool operation."""
    success: bool
    data: Any = None
    error: Optional[str] = None
    execution_time: float = 0.0

    def to_dict(self) -> dict:
        result = {"success": self.success}
        if self.data is not None:
            result["data"] = self.data
        if self.error:
            result["error"] = self.error
        result["execution_time"] = self.execution_time
        return result


class AgentTools:
    """
    Agent tool implementations for the MCP server.

    Provides access to the agent swarm for task delegation.
    """

    def __init__(self, swarm_orchestrator, model_manager=None):
        self.swarm = swarm_orchestrator
        self.model_manager = model_manager
        self._setup_agents()

    def _setup_agents(self):
        """Set up agent factories."""
        from farnsworth.agents.specialist_agents import (
            create_code_agent,
            create_reasoning_agent,
            create_research_agent,
            create_creative_agent,
        )

        self.swarm.register_agent_factory("code", create_code_agent)
        self.swarm.register_agent_factory("reasoning", create_reasoning_agent)
        self.swarm.register_agent_factory("research", create_research_agent)
        self.swarm.register_agent_factory("creative", create_creative_agent)

        # Set model manager
        if self.model_manager:
            self.swarm.llm_backend = self.model_manager

    async def delegate_task(
        self,
        task: str,
        agent_type: str = "auto",
        context: Optional[dict] = None,
        priority: int = 5,
        timeout: float = 120.0,
    ) -> AgentToolResult:
        """
        Delegate a task to a specialist agent.

        Args:
            task: Task description
            agent_type: Type of agent ("code", "reasoning", "research", "creative", "auto")
            context: Optional context dictionary
            priority: Task priority (1-10)
            timeout: Maximum wait time in seconds

        Returns:
            AgentToolResult with output and metadata
        """
        import time
        start_time = time.time()

        try:
            # Infer agent type if auto
            if agent_type == "auto":
                agent_type = self._infer_agent_type(task)

            # Spawn agent if needed
            agent = await self.swarm.spawn_agent(agent_type)
            if agent is None:
                # Try to use existing agent
                for existing in self.swarm.state.active_agents.values():
                    if existing.name.lower().startswith(agent_type):
                        agent = existing
                        break

            if agent is None:
                return AgentToolResult(
                    success=False,
                    error=f"Could not spawn agent of type: {agent_type}",
                    execution_time=time.time() - start_time,
                )

            # Execute task
            result = await agent.execute(task, context)

            return AgentToolResult(
                success=result.success,
                data={
                    "output": result.output,
                    "confidence": result.confidence,
                    "agent_type": agent_type,
                    "agent_id": agent.agent_id,
                    "metadata": result.metadata,
                },
                execution_time=time.time() - start_time,
            )

        except Exception as e:
            logger.error(f"Delegate task failed: {e}")
            return AgentToolResult(
                success=False,
                error=str(e),
                execution_time=time.time() - start_time,
            )

    def _infer_agent_type(self, task: str) -> str:
        """Infer the best agent type for a task."""
        task_lower = task.lower()

        if any(kw in task_lower for kw in ["code", "function", "implement", "debug", "fix bug"]):
            return "code"
        elif any(kw in task_lower for kw in ["reason", "think", "analyze", "math", "logic"]):
            return "reasoning"
        elif any(kw in task_lower for kw in ["research", "find", "search", "look up"]):
            return "research"
        elif any(kw in task_lower for kw in ["write", "creative", "story", "compose"]):
            return "creative"

        return "reasoning"  # Default

    async def execute_multi_task(
        self,
        main_task: str,
        subtasks: list[str],
        context: Optional[dict] = None,
    ) -> AgentToolResult:
        """
        Execute a main task with parallel subtasks.

        Args:
            main_task: Main task description
            subtasks: List of subtask descriptions
            context: Optional shared context

        Returns:
            AgentToolResult with combined results
        """
        import time
        start_time = time.time()

        try:
            results = await self.swarm.execute_with_subtasks(
                main_task=main_task,
                subtasks=subtasks,
                context=context,
            )

            return AgentToolResult(
                success=all(r.success for r in results),
                data={
                    "main_task": main_task,
                    "subtask_count": len(subtasks),
                    "results": [
                        {
                            "success": r.success,
                            "output": r.output[:500] if r.output else None,
                            "confidence": r.confidence,
                        }
                        for r in results
                    ],
                },
                execution_time=time.time() - start_time,
            )

        except Exception as e:
            logger.error(f"Multi-task execution failed: {e}")
            return AgentToolResult(
                success=False,
                error=str(e),
                execution_time=time.time() - start_time,
            )

    async def get_agent_status(self, agent_id: Optional[str] = None) -> AgentToolResult:
        """
        Get status of agents.

        Args:
            agent_id: Specific agent ID, or None for all agents

        Returns:
            AgentToolResult with agent status information
        """
        try:
            if agent_id:
                agent = self.swarm.state.active_agents.get(agent_id)
                if agent:
                    return AgentToolResult(
                        success=True,
                        data=agent.get_status(),
                    )
                else:
                    return AgentToolResult(
                        success=False,
                        error=f"Agent not found: {agent_id}",
                    )
            else:
                status = self.swarm.get_swarm_status()
                return AgentToolResult(
                    success=True,
                    data=status,
                )

        except Exception as e:
            logger.error(f"Get agent status failed: {e}")
            return AgentToolResult(success=False, error=str(e))

    async def get_task_status(self, task_id: str) -> AgentToolResult:
        """
        Get status of a specific task.
        """
        try:
            status = self.swarm.get_task_status(task_id)
            if status:
                return AgentToolResult(success=True, data=status)
            else:
                return AgentToolResult(
                    success=False,
                    error=f"Task not found: {task_id}",
                )

        except Exception as e:
            logger.error(f"Get task status failed: {e}")
            return AgentToolResult(success=False, error=str(e))

    async def list_available_agents(self) -> AgentToolResult:
        """
        List available agent types and their capabilities.
        """
        try:
            from farnsworth.agents.base_agent import AgentCapability

            agent_info = {
                "code": {
                    "description": "Programming specialist for code generation, analysis, and debugging",
                    "capabilities": [
                        AgentCapability.CODE_GENERATION.value,
                        AgentCapability.CODE_ANALYSIS.value,
                        AgentCapability.CODE_DEBUGGING.value,
                    ],
                },
                "reasoning": {
                    "description": "Logic specialist for step-by-step reasoning and analysis",
                    "capabilities": [
                        AgentCapability.REASONING.value,
                        AgentCapability.MATH.value,
                        AgentCapability.PLANNING.value,
                    ],
                },
                "research": {
                    "description": "Research specialist for information gathering and synthesis",
                    "capabilities": [
                        AgentCapability.RESEARCH.value,
                        AgentCapability.SUMMARIZATION.value,
                    ],
                },
                "creative": {
                    "description": "Creative specialist for writing and ideation",
                    "capabilities": [
                        AgentCapability.CREATIVE_WRITING.value,
                    ],
                },
            }

            return AgentToolResult(
                success=True,
                data={
                    "agent_types": agent_info,
                    "active_count": len(self.swarm.state.active_agents),
                    "max_concurrent": self.swarm.max_concurrent,
                },
            )

        except Exception as e:
            logger.error(f"List agents failed: {e}")
            return AgentToolResult(success=False, error=str(e))
