# backend/src/agent/tools.py
# #region AgentChat.Tools [C:4] [TYPE Module] [SEMANTICS agent-chat,tools,langchain]
# @DEFGROUP AgentChat Native LangChain @tool functions.
# @REJECTED StructuredTool wrapping — native @tool is the single source of truth.
# @REJECTED StructuredTool wrapping — native @tool is the single source of truth.
# @RATIONALE LangChain @tool decorator chosen over direct FastAPI calls for LangGraph compatibility — tools are auto-registered in the agent's tool-calling loop.

import os

import httpx
from langchain_core.tools import tool
from pydantic import BaseModel, Field

from src.agent.context import get_service_jwt, get_user_jwt

FASTAPI_URL = os.getenv("FASTAPI_URL", "http://backend:8000")


def _dual_auth_headers() -> dict[str, str]:
    """Build dual-identity headers for tool→FastAPI calls.
    Authorization: service JWT (authenticates the agent).
    X-User-JWT: user JWT (authorizes the operation — RBAC).
    Falls back to SERVICE_JWT env var if ContextVar is not set
    (e.g., in Gradio's async context where ContextVars don't propagate).
    """
    svc_jwt = get_service_jwt() or os.getenv("SERVICE_JWT", "")
    user_jwt = get_user_jwt() or ""
    headers = {}
    if svc_jwt:
        headers["Authorization"] = f"Bearer {svc_jwt}"
    if user_jwt:
        headers["X-User-JWT"] = user_jwt
    return headers


# ── Tool: search_dashboards ──
class SearchDashboardsInput(BaseModel):
    query: str = Field(description="Search query for dashboard name")
    env_id: str | None = Field(default=None, description="Environment ID (e.g. 'prod', 'ss-dev')")


# @ingroup AgentChat
# @PRE User authenticated via dual-identity JWT
# @POST Returns JSON string result from FastAPI
# @SIDE_EFFECT HTTP call to FastAPI backend

@tool(args_schema=SearchDashboardsInput)
async def search_dashboards(query: str, env_id: str | None = None) -> str:
    """Search and list dashboards by name, with optional environment filter.
    Pass env_id like 'prod', 'ss-dev', or 'ss-preprod' to filter by environment.
    """
    params = {"q": query, "env_id": env_id or ""}
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{FASTAPI_URL}/api/dashboards",
            params=params,
            headers=_dual_auth_headers(),
        )
        return resp.text


# ── Tool: get_health_summary ──
# @ingroup AgentChat
# @PRE User authenticated via dual-identity JWT
# @POST Returns JSON string result from FastAPI
# @SIDE_EFFECT HTTP call to FastAPI backend
@tool
async def get_health_summary() -> str:
    """Get system health summary — dashboard validation status, recent failures."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{FASTAPI_URL}/api/dashboards/health",
            headers=_dual_auth_headers(),
        )
        return resp.text


# ── Tool: list_environments ──
# @ingroup AgentChat
# @PRE User authenticated via dual-identity JWT
# @POST Returns JSON string result from FastAPI
# @SIDE_EFFECT HTTP call to FastAPI backend
@tool
async def list_environments() -> str:
    """List configured deployment environments."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{FASTAPI_URL}/api/settings/environments",
            headers=_dual_auth_headers(),
        )
        return resp.text


# ── Tool: get_task_status ──
# @ingroup AgentChat
# @PRE User authenticated via dual-identity JWT
# @POST Returns JSON string result from FastAPI
# @SIDE_EFFECT HTTP call to FastAPI backend
@tool
async def get_task_status(task_id: str) -> str:
    """Check the status of a background task by its task_id."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{FASTAPI_URL}/api/tasks/{task_id}",
            headers=_dual_auth_headers(),
        )
        return resp.text


# ── All available tools for the agent ──
def get_all_tools() -> list:
    return [
        search_dashboards,
        get_health_summary,
        list_environments,
        get_task_status,
    ]
# #endregion AgentChat.Tools
