"""
Gateway Client for Coherence MCP Adapter.

Handles JWT generation and communication with the Coherence Gateway.
"""

import logging
import time
from typing import Any

import httpx
from jose import jwt

logger = logging.getLogger(__name__)


class GatewayClient:
    """Client for interacting with Coherence Gateway."""

    def __init__(self, gateway_url: str, jwt_secret: str):
        self.gateway_url = gateway_url.rstrip("/")
        self.jwt_secret = jwt_secret
        self.client = httpx.AsyncClient(timeout=30.0)

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.client.aclose()

    def _generate_jwt(self, tool_name: str, expiry_minutes: int = 5) -> str:
        """Generate JWT token with tool capability."""
        payload = {
            "sub": "claude-desktop",
            "tool": tool_name,
            "exp": int(time.time()) + (expiry_minutes * 60),
            "iat": int(time.time()),
        }
        return jwt.encode(payload, self.jwt_secret, algorithm="HS256")

    async def execute_tool(
        self, tool_name: str, parameters: dict[str, Any]
    ) -> dict[str, Any]:
        """
        Execute a tool via the gateway.

        Args:
            tool_name: Name of the tool to execute
            parameters: Tool parameters

        Returns:
            Tool execution result
        """
        try:
            # Generate JWT for this tool
            token = self._generate_jwt(tool_name)

            # Prepare request payload
            # The gateway expects tool at top level for OPA and in input for LangServe
            request_payload = {
                "tool": tool_name,  # For OPA authorization
                "input": {
                    "tool": tool_name,  # For LangServe runnable
                    "input": parameters,  # Actual tool parameters
                },
            }

            logger.debug(f"Executing tool {tool_name} with payload: {request_payload}")

            # Make request to gateway
            response = await self.client.post(
                f"{self.gateway_url}/invoke",
                json=request_payload,
                headers={
                    "Authorization": f"Bearer {token}",
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                },
            )

            # Handle response
            if response.status_code == 200:
                result = response.json()
                logger.info(f"Tool {tool_name} executed successfully")
                return result
            elif response.status_code == 401:
                logger.error(f"Authentication failed for tool {tool_name}")
                return {"error": "Authentication failed"}
            elif response.status_code == 403:
                logger.error(f"Authorization failed for tool {tool_name}")
                return {"error": "Not authorized to use this tool"}
            else:
                # Check if we got HTML instead of JSON
                content_type = response.headers.get("content-type", "")
                if "text/html" in content_type:
                    logger.error(
                        f"Gateway returned HTML instead of JSON (status {response.status_code}). "
                        f"This usually indicates a configuration error or missing runner."
                    )
                    # Try to extract meaningful error from HTML if possible
                    return {"error": f"Gateway configuration error: {response.status_code} - Runner may not be configured for tool '{tool_name}'"}
                else:
                    logger.error(
                        f"Gateway returned {response.status_code}: {response.text}"
                    )
                    return {"error": f"Gateway error: {response.status_code}"}

        except httpx.HTTPError as e:
            logger.error(f"HTTP error executing tool {tool_name}: {e}")
            return {"error": f"HTTP error: {str(e)}"}
        except Exception as e:
            logger.error(f"Error executing tool {tool_name}: {e}", exc_info=True)
            return {"error": f"Execution error: {str(e)}"}

    async def health_check(self) -> bool:
        """Check if the gateway is healthy."""
        try:
            response = await self.client.get(f"{self.gateway_url}/health")
            if response.status_code == 200:
                data = response.json()
                status = data.get("status")
                logger.info(f"Gateway health: {status}")
                return status in ["healthy", "degraded"]
            return False
        except Exception as e:
            logger.error(f"Health check failed: {e}")
            return False
