"""
Tool Registry - Central registry for all available tools
"""
from typing import Dict, List, Optional, Type
from app.tools.base import Tool
import logging

logger = logging.getLogger(__name__)


class ToolRegistry:
    """
    Central registry for managing all available tools.

    Tools are registered by name and can be filtered by:
    - Category (sales, orders, inventory, etc.)
    - Agent type (ecommerce, pos, crm, general)
    """

    def __init__(self):
        self._tools: Dict[str, Tool] = {}
        self._categories: Dict[str, List[str]] = {}  # category -> list of tool names
        self._agent_tools: Dict[str, List[str]] = {}  # agent_type -> list of tool names

    def register(self, tool: Tool) -> None:
        """
        Register a tool in the registry.

        Args:
            tool: Tool instance to register
        """
        if tool.name in self._tools:
            logger.warning(f"Tool '{tool.name}' is being re-registered")

        self._tools[tool.name] = tool

        # Index by category
        category = tool.category
        if category not in self._categories:
            self._categories[category] = []
        if tool.name not in self._categories[category]:
            self._categories[category].append(tool.name)

        # Index by agent type
        for agent_type in tool.agent_types:
            if agent_type not in self._agent_tools:
                self._agent_tools[agent_type] = []
            if tool.name not in self._agent_tools[agent_type]:
                self._agent_tools[agent_type].append(tool.name)

        logger.info(f"Registered tool: {tool.name} (category: {category}, agents: {tool.agent_types})")

    def unregister(self, tool_name: str) -> bool:
        """
        Remove a tool from the registry.

        Args:
            tool_name: Name of the tool to remove

        Returns:
            True if tool was removed, False if not found
        """
        if tool_name not in self._tools:
            return False

        tool = self._tools[tool_name]

        # Remove from category index
        if tool.category in self._categories:
            self._categories[tool.category] = [
                t for t in self._categories[tool.category] if t != tool_name
            ]

        # Remove from agent type index
        for agent_type in tool.agent_types:
            if agent_type in self._agent_tools:
                self._agent_tools[agent_type] = [
                    t for t in self._agent_tools[agent_type] if t != tool_name
                ]

        del self._tools[tool_name]
        logger.info(f"Unregistered tool: {tool_name}")
        return True

    def get(self, tool_name: str) -> Optional[Tool]:
        """
        Get a tool by name.

        Args:
            tool_name: Name of the tool

        Returns:
            Tool instance or None if not found
        """
        return self._tools.get(tool_name)

    def get_all(self) -> List[Tool]:
        """Get all registered tools"""
        return list(self._tools.values())

    def get_by_category(self, category: str) -> List[Tool]:
        """
        Get all tools in a specific category.

        Args:
            category: Category name (e.g., 'sales', 'orders')

        Returns:
            List of tools in that category
        """
        tool_names = self._categories.get(category, [])
        return [self._tools[name] for name in tool_names if name in self._tools]

    def get_for_agent(self, agent_type: str) -> List[Tool]:
        """
        Get all tools available for a specific agent type.

        Args:
            agent_type: Agent type (e.g., 'ecommerce', 'pos', 'general')

        Returns:
            List of tools available for that agent
        """
        # Always include general tools
        tool_names = set(self._agent_tools.get("general", []))

        # Add agent-specific tools
        if agent_type != "general":
            tool_names.update(self._agent_tools.get(agent_type, []))

        return [self._tools[name] for name in tool_names if name in self._tools]

    def get_function_schemas(self, agent_type: str = "general") -> List[Dict]:
        """
        Get function schemas for all tools available to an agent.
        This is used to pass to the AI model for function calling.

        Args:
            agent_type: Agent type to get tools for

        Returns:
            List of function schemas in OpenAI/Anthropic format
        """
        tools = self.get_for_agent(agent_type)
        return [tool.to_function_schema() for tool in tools]

    def list_categories(self) -> List[str]:
        """Get all registered categories"""
        return list(self._categories.keys())

    def list_agent_types(self) -> List[str]:
        """Get all registered agent types"""
        return list(self._agent_tools.keys())

    @property
    def count(self) -> int:
        """Total number of registered tools"""
        return len(self._tools)

    def __contains__(self, tool_name: str) -> bool:
        return tool_name in self._tools

    def __repr__(self) -> str:
        return f"<ToolRegistry: {self.count} tools>"


# Global singleton registry
tool_registry = ToolRegistry()


def register_tool(tool_class: Type[Tool]) -> Type[Tool]:
    """
    Decorator to automatically register a tool class.

    Usage:
        @register_tool
        class GetSalesTool(ReadOnlyTool):
            ...
    """
    tool_instance = tool_class()
    tool_registry.register(tool_instance)
    return tool_class
