"""
Agent Manager

Manages multiple agents and handles agent switching.
"""

from dataclasses import dataclass
from pathlib import Path
from typing import Any, Optional

from groknroll.agents.base_agent import AgentResponse, BaseAgent
from groknroll.agents.build_agent import BuildAgent
from groknroll.agents.custom_agent import create_agent_from_config
from groknroll.agents.plan_agent import PlanAgent
from groknroll.config.agent_config import AgentConfigLoader


@dataclass
class AgentInfo:
    """Information about an agent"""

    name: str
    description: str
    capabilities: list[str]
    is_active: bool


class AgentManager:
    """
    Agent Manager

    Manages multiple agents and provides agent switching functionality.
    Similar to OpenCode's Tab key agent switching.
    """

    def __init__(
        self,
        project_path: Path,
        model: str = "gpt-4o-mini",
        max_cost: float = 5.0,
        timeout: int = 300,
    ):
        """
        Initialize agent manager

        Args:
            project_path: Project root path
            model: Default model for agents
            max_cost: Default max cost
            timeout: Default timeout
        """
        self.project_path = project_path
        self.model = model
        self.max_cost = max_cost
        self.timeout = timeout

        # Initialize agents
        self.agents: dict[str, BaseAgent] = {
            "build": BuildAgent(
                project_path=project_path, model=model, max_cost=max_cost, timeout=timeout
            ),
            "plan": PlanAgent(
                project_path=project_path, model=model, max_cost=max_cost, timeout=timeout
            ),
        }

        # Load custom agents from configuration
        self.load_custom_agents()

        # Current agent
        self.current_agent_name = "build"  # Default to build agent

    @property
    def current_agent(self) -> BaseAgent:
        """Get current active agent"""
        return self.agents[self.current_agent_name]

    def switch(self, agent_name: str) -> bool:
        """
        Switch to different agent

        Args:
            agent_name: Agent name (build/plan)

        Returns:
            True if switched successfully
        """
        if agent_name not in self.agents:
            return False

        self.current_agent_name = agent_name
        return True

    def execute(
        self, task: str, agent: Optional[str] = None, context: Optional[dict[str, Any]] = None
    ) -> AgentResponse:
        """
        Execute task with current or specified agent

        Args:
            task: Task description
            agent: Agent name (uses current if None)
            context: Additional context

        Returns:
            AgentResponse
        """
        # Use specified agent or current
        agent_name = agent or self.current_agent_name

        if agent_name not in self.agents:
            return AgentResponse(
                success=False,
                message=f"Unknown agent: {agent_name}",
                agent_name=agent_name,
                task=task,
            )

        # Execute with agent
        return self.agents[agent_name].execute(task, context)

    def get_agent(self, name: str) -> Optional[BaseAgent]:
        """Get agent by name"""
        return self.agents.get(name)

    def list_agents(self) -> list[AgentInfo]:
        """List all available agents"""
        return [
            AgentInfo(
                name=name,
                description=agent.config.description,
                capabilities=agent.get_capabilities(),
                is_active=(name == self.current_agent_name),
            )
            for name, agent in self.agents.items()
        ]

    def get_stats(self) -> dict[str, Any]:
        """Get statistics for all agents"""
        return {
            "current_agent": self.current_agent_name,
            "agents": {name: agent.get_stats() for name, agent in self.agents.items()},
        }

    def register_agent(self, name: str, agent: BaseAgent) -> None:
        """
        Register custom agent

        Args:
            name: Agent name
            agent: Agent instance
        """
        self.agents[name] = agent

    def unregister_agent(self, name: str) -> bool:
        """
        Unregister agent

        Args:
            name: Agent name

        Returns:
            True if unregistered successfully
        """
        if name in ["build", "plan"]:
            # Cannot unregister core agents
            return False

        if name in self.agents:
            del self.agents[name]

            # Switch to build if current agent was removed
            if self.current_agent_name == name:
                self.current_agent_name = "build"

            return True

        return False

    def load_custom_agents(self) -> dict[str, BaseAgent]:
        """
        Load custom agents from configuration

        Loads from:
        1. groknroll.json (agent section)
        2. .groknroll/agent/<name>.md files

        Returns:
            Dict of loaded agent names to instances
        """
        loader = AgentConfigLoader(self.project_path)

        try:
            configs = loader.load_all()
        except (ValueError, FileNotFoundError):
            return {}

        loaded = {}

        for name, config_data in configs.items():
            # Skip if already exists (don't override built-in agents)
            if name in self.agents:
                continue

            try:
                # Validate configuration
                loader.validate_config(config_data)

                # Create custom agent
                agent = create_agent_from_config(config_data, self.project_path)

                # Register agent
                self.agents[name] = agent
                loaded[name] = agent

            except ValueError:
                # Skip invalid configurations
                continue

        return loaded

    def reload_custom_agents(self) -> dict[str, BaseAgent]:
        """
        Reload all custom agents from configuration

        Removes existing custom agents and reloads from files.

        Returns:
            Dict of loaded agent names to instances
        """
        # Remove all custom agents (keep build and plan)
        custom_agent_names = [name for name in self.agents.keys() if name not in ["build", "plan"]]

        for name in custom_agent_names:
            self.unregister_agent(name)

        # Reload from configuration
        return self.load_custom_agents()

    def __repr__(self) -> str:
        return f"AgentManager(current={self.current_agent_name}, agents={list(self.agents.keys())})"
