"""ClampdClient — gateway HTTP client."""

from __future__ import annotations

from typing import Any

import httpx
from pydantic import BaseModel

from clampd.auth import make_agent_jwt


class ProxyResponse(BaseModel):
    request_id: str
    allowed: bool
    risk_score: float
    scope_granted: str | None = None
    tool_response: Any | None = None
    denial_reason: str | None = None
    latency_ms: int
    degraded_stages: list[str] = []
    session_flags: list[str] = []


class ClampdBlockedError(Exception):
    """Raised when Clampd denies a tool call."""

    def __init__(self, reason: str, *, risk_score: float = 1.0, response: ProxyResponse | None = None):
        self.reason = reason
        self.risk_score = risk_score
        self.response = response
        super().__init__(f"Blocked: {reason} (risk={risk_score:.2f})")


class ClampdClient:
    """HTTP client for the Clampd gateway."""

    def __init__(
        self,
        *,
        gateway_url: str = "http://localhost:8080",
        agent_id: str,
        api_key: str = "clmpd_demo_key",
        secret: str | None = None,
        timeout: float = 30.0,
    ) -> None:
        self.gateway_url = gateway_url.rstrip("/")
        self.agent_id = agent_id
        self.api_key = api_key
        self._jwt = make_agent_jwt(agent_id, secret=secret)
        self._http = httpx.Client(timeout=timeout)

    def _headers(self) -> dict[str, str]:
        return {
            "Authorization": f"Bearer {self._jwt}",
            "X-AG-Key": self.api_key,
            "Content-Type": "application/json",
        }

    def proxy(self, tool: str, params: dict[str, Any], target_url: str = "", prompt_context: str | None = None) -> ProxyResponse:
        body: dict[str, Any] = {"tool": tool, "params": params, "target_url": target_url}
        if prompt_context:
            body["prompt_context"] = prompt_context
        return self._post("/v1/proxy", body)

    def verify(self, tool: str, params: dict[str, Any], target_url: str = "") -> ProxyResponse:
        return self._post("/v1/verify", {"tool": tool, "params": params, "target_url": target_url})

    def inspect(self, tool: str, response_data: Any, request_id: str = "") -> ProxyResponse:
        """Inspect a tool response for PII, anomalies, or policy violations."""
        body: dict[str, Any] = {"tool": tool, "response_data": response_data}
        if request_id:
            body["request_id"] = request_id
        return self._post("/v1/inspect", body)

    def _post(self, path: str, body: dict[str, Any]) -> ProxyResponse:
        try:
            resp = self._http.post(f"{self.gateway_url}{path}", headers=self._headers(), json=body)
        except Exception as e:
            return ProxyResponse(request_id="error", allowed=False, risk_score=1.0, denial_reason=str(e), latency_ms=0)

        if resp.status_code == 200:
            return ProxyResponse.model_validate(resp.json())

        return ProxyResponse(request_id="error", allowed=False, risk_score=1.0, denial_reason=resp.text, latency_ms=0)

    def close(self) -> None:
        self._http.close()

    def __enter__(self) -> ClampdClient:
        return self

    def __exit__(self, *exc: object) -> None:
        self.close()
