"""MCP tool discovery endpoint."""

from fastapi import APIRouter, Depends, Path
from sqlalchemy.orm import Session

from robosystems.database import get_db_session
from robosystems.logger import logger
from robosystems.middleware.auth.dependencies import get_current_user_with_graph
from robosystems.middleware.graph import get_graph_repository
from robosystems.middleware.graph.types import GRAPH_OR_SUBGRAPH_ID_PATTERN
from robosystems.middleware.graph.utils import MultiTenantUtils
from robosystems.middleware.otel.metrics import (
  endpoint_metrics_decorator,
  get_endpoint_metrics,
)
from robosystems.middleware.rate_limits import (
  subscription_aware_rate_limit_dependency,
)
from robosystems.middleware.robustness import CircuitBreakerManager
from robosystems.models.api.common import RESOURCE_ERROR_RESPONSES
from robosystems.models.api.graphs.mcp import MCPToolsResponse
from robosystems.models.core import User
from robosystems.routers.graphs.mcp.handlers import MCPHandler

# Import MCP components
from .handlers import validate_mcp_access

router = APIRouter()

# Circuit breaker instance
circuit_breaker = CircuitBreakerManager()


def _get_mcp_operation_type(graph_id: str) -> str:
  # Shared repos route to reader cluster; user graphs always use writer for consistency
  if MultiTenantUtils.is_shared_repository(graph_id):
    return "read"
  else:
    return "write"


@router.get(
  "/tools",
  response_model=MCPToolsResponse,
  summary="List MCP Tools",
  description="Returns tool schemas with capability hints (streaming, caching, timeouts) per tool. Tool list is context-aware by graph type; identical for parent graphs and subgraphs.",
  operation_id="listMcpTools",
  responses={**RESOURCE_ERROR_RESPONSES},
)
@endpoint_metrics_decorator(
  "/v1/graphs/{graph_id}/mcp/tools", business_event_type="mcp_tools_listed"
)
async def list_mcp_tools(
  graph_id: str = Path(
    ...,
    description="Graph database identifier",
    pattern=GRAPH_OR_SUBGRAPH_ID_PATTERN,
  ),
  current_user: User = Depends(get_current_user_with_graph),
  db: Session = Depends(get_db_session),
  _rate_limit: None = Depends(subscription_aware_rate_limit_dependency),
) -> MCPToolsResponse:
  # Validate access based on graph type
  await validate_mcp_access(graph_id, current_user, db, "read")

  # Use proper operation type based on graph type for consistent routing
  operation_type = _get_mcp_operation_type(graph_id)
  repository = await get_graph_repository(graph_id, operation_type)

  # Check circuit breaker for list_tools operation
  circuit_breaker.check_circuit(graph_id, "list_tools")

  try:
    # Create handler directly for tool discovery
    handler = MCPHandler(repository, graph_id, current_user)
    tools = await handler.get_tools()

    # Enhance tool definitions with capability hints for AI agents
    enhanced_tools = []
    for tool in tools:
      # Add capability indicators
      tool_name = tool["name"]

      # Query tools support streaming
      if "cypher" in tool_name:
        tool["capabilities"] = {
          "streaming": True,
          "progress": True,
          "cacheable": False,
          "timeout_seconds": 300,
        }
      # Schema tools support caching
      elif "schema" in tool_name:
        tool["capabilities"] = {
          "streaming": False,
          "progress": True,
          "cacheable": True,
          "cache_ttl_seconds": 3600,
          "timeout_seconds": 60,
        }
      # Info tools are fast and cacheable
      elif "info" in tool_name or "describe" in tool_name:
        tool["capabilities"] = {
          "streaming": False,
          "progress": False,
          "cacheable": True,
          "cache_ttl_seconds": 300,
          "timeout_seconds": 30,
        }
      else:
        tool["capabilities"] = {
          "streaming": False,
          "progress": False,
          "cacheable": False,
          "timeout_seconds": 60,
        }

      enhanced_tools.append(tool)

    # Record successful operation
    circuit_breaker.record_success(graph_id, "list_tools")

    # Record metrics
    metrics_instance = get_endpoint_metrics()
    metrics_instance.record_business_event(
      endpoint="/v1/graphs/{graph_id}/mcp/tools",
      method="GET",
      event_type="mcp_tools_listed",
      event_data={
        "graph_id": graph_id,
        "tool_count": len(enhanced_tools),
        "is_shared_repo": MultiTenantUtils.is_shared_repository(graph_id),
      },
      user_id=current_user.id,
    )

    logger.info(
      f"Listed {len(enhanced_tools)} MCP tools for graph {graph_id}",
      extra={
        "graph_id": graph_id,
        "user_id": str(current_user.id),
        "tool_count": len(enhanced_tools),
      },
    )

    return MCPToolsResponse(tools=enhanced_tools)

  except Exception as e:
    # Record failed operation
    circuit_breaker.record_failure(graph_id, "list_tools")

    logger.error(
      f"Failed to list MCP tools for graph {graph_id}: {e}",
      extra={
        "graph_id": graph_id,
        "user_id": str(current_user.id),
        "error": str(e),
      },
    )

    # Record error metrics
    metrics_instance = get_endpoint_metrics()
    metrics_instance.record_business_event(
      endpoint="/v1/graphs/{graph_id}/mcp/tools",
      method="GET",
      event_type="mcp_tools_list_failed",
      event_data={
        "graph_id": graph_id,
        "error_type": type(e).__name__,
      },
      user_id=current_user.id,
    )

    # Handle exception securely
    from robosystems.security import handle_exception_securely

    handle_exception_securely(
      e, additional_context={"operation": "list_mcp_tools", "graph_id": graph_id}
    )
    raise  # This should never be reached, but satisfies type checker
