"""Gateway SDK client for script tool sandboxes."""

from __future__ import annotations

import logging
import os
from typing import Any

import httpx

logger = logging.getLogger(__name__)


class GatewayClient:
    """Thin async HTTP client for communicating with MCP Gateway from sandboxes.

    Auto-configures from environment variables:
    - MCPGATEWAY_TOKEN: Bearer token for authentication
    - MCPGATEWAY_URL: Gateway base URL (default: http://localhost:8000)
    """

    def __init__(
        self,
        token: str | None = None,
        base_url: str | None = None,
    ) -> None:
        self._token = token or os.environ.get("MCPGATEWAY_TOKEN", "")
        self._base_url = base_url or os.environ.get("MCPGATEWAY_URL", "http://localhost:8000")
        self._client = httpx.AsyncClient(
            base_url=self._base_url,
            headers={"Authorization": f"Bearer {self._token}"},
            timeout=30.0,
        )

    async def execute_tool(
        self, tool_name: str, arguments: dict[str, Any] | None = None
    ) -> dict[str, Any]:
        """Call a raw MCP tool via the gateway.

        Args:
            tool_name: Prefixed tool name (e.g. "SALESFORCE__opps_list")
            arguments: Tool arguments dict

        Returns:
            Tool execution result dict
        """
        resp = await self._client.post(
            "/api/v1/sdk/tools/execute",
            json={
                "tool_name": tool_name,
                "arguments": arguments or {},
            },
        )
        resp.raise_for_status()
        data = resp.json()
        if "error" in data and data["error"]:
            raise RuntimeError(f"Tool execution failed: {data['error']}")
        return data.get("result", data)

    async def search_tools(self, query: str, limit: int = 5) -> list[dict[str, Any]]:
        """Semantic search across enabled tools.

        Args:
            query: Natural language search query
            limit: Max results (default 5)

        Returns:
            List of tool dicts with tool_name, description, server_name, score, input_schema
        """
        resp = await self._client.post(
            "/api/v1/sdk/tools/search",
            json={
                "query": query,
                "limit": limit,
            },
        )
        resp.raise_for_status()
        return resp.json().get("tools", [])

    async def cache_get(self, key: str) -> Any | None:
        """Read from gateway cache.

        Returns None if key not found or cache unavailable.
        Graceful degradation -- never raises on cache miss.
        """
        try:
            resp = await self._client.get(f"/api/v1/sdk/cache/{key}")
            if resp.status_code == 404:
                return None
            resp.raise_for_status()
            return resp.json().get("value")
        except httpx.HTTPError as exc:
            logger.debug("cache_get failed for key '%s': %s", key, exc)
            return None

    async def cache_set(self, key: str, value: Any, ttl: int = 300) -> None:
        """Write to gateway cache with TTL.

        Graceful degradation -- silently fails if cache unavailable.
        """
        try:
            resp = await self._client.put(
                f"/api/v1/sdk/cache/{key}",
                json={
                    "value": value,
                    "ttl": ttl,
                },
            )
            resp.raise_for_status()
        except httpx.HTTPError as exc:
            logger.debug("cache_set failed for key '%s': %s", key, exc)

    async def close(self) -> None:
        """Close the HTTP client."""
        await self._client.aclose()

    async def __aenter__(self) -> GatewayClient:
        return self

    async def __aexit__(self, *args: Any) -> None:
        await self.close()
