"""MCP tools module with auto-discovery and registration.

This module registers ALL tools at server startup.
Permission-based access control is handled by PermissionMiddleware
which filters the tool list per-user via the on_list_tools hook.

Access Levels (enforced by middleware):
1. Unauthenticated → Only @public tools visible
2. Authenticated (not ptAdmin) → @public + matching @requires_permissions
3. ptAdmin → All tools visible

Usage:
    from point_topic_mcp.tools import get_all_tools, get_tool_function

    # Get all tool functions
    tools = get_all_tools()

    # Get a specific tool by name
    tool_func = get_tool_function("query_database")
"""

import importlib
import pkgutil
import inspect
from pathlib import Path
from typing import Callable, Any

# Cache for discovered tools
_discovered_tools: list[Callable] | None = None
_tool_lookup: dict[str, Callable] | None = None


def _discover_tools() -> tuple[list[Callable], dict[str, Callable] | None]:
    """Discover all tool functions in the tools directory.

    Returns:
        Tuple of (list of tool functions, dict mapping names to functions)
    """
    global _discovered_tools, _tool_lookup

    if _discovered_tools is not None:
        return _discovered_tools, _tool_lookup

    tools: list[Callable] = []
    lookup: dict[str, Callable] = {}

    # Get the tools package directory
    tools_dir = Path(__file__).parent

    # Discover all Python modules in this directory
    for module_info in pkgutil.iter_modules([str(tools_dir)]):
        # Skip __init__ and any private modules
        if module_info.name.startswith("_"):
            continue

        try:
            # Import the module
            module = importlib.import_module(
                f".{module_info.name}", package="point_topic_mcp.tools"
            )

            # Find all functions defined in this module (not imported from elsewhere)
            for name, obj in inspect.getmembers(module, inspect.isfunction):
                # Skip private functions
                if name.startswith("_"):
                    continue

                # Only register functions actually defined in this module
                if obj.__module__ == module.__name__:
                    tools.append(obj)
                    lookup[name] = obj

        except Exception as e:
            import traceback

            print(f"[MCP] Warning: Failed to load tools from {module_info.name}: {e}")
            traceback.print_exc()
            # Continue with other modules even if one fails

    _discovered_tools = tools
    _tool_lookup = lookup

    return tools, lookup


def get_all_tools() -> list[Callable]:
    """Get all discovered tool functions.

    Returns:
        List of all tool functions in the tools directory
    """
    tools, _ = _discover_tools()
    return tools


def get_tool_function(name: str) -> Callable | None:
    """Get a specific tool function by name.

    Args:
        name: Name of the tool function to retrieve

    Returns:
        The tool function if found, None otherwise
    """
    _, lookup = _discover_tools()
    if lookup is None:
        return None
    return lookup.get(name)


def register_tools(mcp):
    """Register all MCP tools by auto-discovering functions in tool modules.

    Automatically finds all Python modules in the tools directory and registers
    every public function (not starting with _) as an MCP tool.

    ALL tools are registered - access control is handled by PermissionMiddleware
    which filters the visible tool list per-user when clients request tools/list.

    Just create a .py file with tool functions - the middleware handles permissions!

    Args:
        mcp: The MCP server instance (FastMCP or official SDK Server)
    """
    # Import here to avoid circular imports
    try:
        from point_topic_mcp.auth import PermissionMiddleware

        # Add permission middleware to handle access control
        # This filters tools in on_list_tools based on user's Auth0 permissions
        mcp.add_middleware(PermissionMiddleware())
        print("[MCP] Permission middleware enabled")
    except Exception as e:
        # Middleware not available (e.g., local dev without auth)
        print(f"[MCP] Permission middleware skipped: {e}")

    # Discover and register all tools
    tools, _ = _discover_tools()

    for tool_func in tools:
        mcp.tool()(tool_func)
        print(f"[MCP] Registered tool: {tool_func.__name__}")

    print(f"[MCP] Total tools registered: {len(tools)}")


__all__ = ["register_tools", "get_all_tools", "get_tool_function"]
