"""Core SDK client — thin HTTP wrapper around Triage Guard FastAPI service."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional

import httpx

# ---------------------------------------------------------------------------
# Config singleton
# ---------------------------------------------------------------------------

_DEFAULT_BASE_URL = "https://guard.trytriage.com"
_DEFAULT_PROMPT_GUARD_URL = "https://darwintreehacks-dev2--triage-guard-promptguardservice-serve.modal.run"
_DEFAULT_TOOL_GUARD_URL = "https://darwintreehacks-dev2--triage-guard-toolguardservice-serve.modal.run"


@dataclass
class _Config:
    api_key: str | None = None
    base_url: str = _DEFAULT_BASE_URL
    prompt_guard_url: str = _DEFAULT_PROMPT_GUARD_URL
    tool_guard_url: str = _DEFAULT_TOOL_GUARD_URL
    timeout: float = 30.0


_config = _Config()


def init(
    api_key: str,
    base_url: str | None = None,
    prompt_guard_url: str | None = None,
    tool_guard_url: str | None = None,
    timeout: float = 30.0,
) -> None:
    """Initialize the Triage SDK.

    Must be called before any check functions.

    Args:
        api_key: Your Triage API key (tsk_...).
        base_url: Optional legacy base URL. If provided, check endpoints are derived as
            <base_url>/v1/prompt-guard and <base_url>/v1/tool-guard unless explicitly
            overridden by prompt_guard_url/tool_guard_url.
        prompt_guard_url: Full Prompt Guard endpoint URL.
        tool_guard_url: Full Tool Guard endpoint URL.
        timeout: HTTP request timeout in seconds.
    """
    normalized_base = (base_url.rstrip("/") if base_url else _DEFAULT_BASE_URL)
    _config.api_key = api_key
    _config.base_url = normalized_base
    _config.prompt_guard_url = (
        prompt_guard_url.rstrip("/")
        if prompt_guard_url
        else (
            f"{normalized_base}/v1/prompt-guard"
            if base_url
            else _DEFAULT_PROMPT_GUARD_URL
        )
    )
    _config.tool_guard_url = (
        tool_guard_url.rstrip("/")
        if tool_guard_url
        else (
            f"{normalized_base}/v1/tool-guard"
            if base_url
            else _DEFAULT_TOOL_GUARD_URL
        )
    )
    _config.timeout = timeout


# ---------------------------------------------------------------------------
# Internal HTTP helpers
# ---------------------------------------------------------------------------


def _headers() -> dict[str, str]:
    if not _config.api_key:
        raise RuntimeError("triage_sdk.init() must be called before making requests")
    return {
        "Authorization": f"Bearer {_config.api_key}",
        "Content-Type": "application/json",
    }


def _post(url: str, body: dict) -> dict:
    """Synchronous POST to configured guard endpoint."""
    resp = httpx.post(url, json=body, headers=_headers(), timeout=_config.timeout)
    resp.raise_for_status()
    return resp.json()


# ---------------------------------------------------------------------------
# Response types
# ---------------------------------------------------------------------------


@dataclass
class InputCheckResult:
    """Result of a prompt injection check."""

    label: str  # "INJECTION" | "BENIGN"
    confidence: float
    latency_ms: float

    @property
    def is_safe(self) -> bool:
        return self.label.strip().lower() == "benign"


@dataclass
class ToolCallCheckResult:
    """Result of a tool-call safety check."""

    malicious: str  # "yes" | "no"
    attacked: str  # "yes" | "no"
    harmfulness: float  # 0.0, 0.5, or 1.0
    composite_score: float  # 0.0, 0.5, or 1.0
    latency_ms: float

    @property
    def is_safe(self) -> bool:
        return self.composite_score == 0.0


@dataclass
class OutputCheckResult:
    """Result of an output safety check. Stub for now."""

    label: str = "SAFE"
    confidence: float = 1.0
    latency_ms: float = 0.0

    @property
    def is_safe(self) -> bool:
        return True


# ---------------------------------------------------------------------------
# Namespace classes
# ---------------------------------------------------------------------------


class _Input:
    """triage_sdk.input.check(text) — detect prompt injection / jailbreak."""

    @staticmethod
    def check(
        text: str,
        model_provider: Optional[str] = None,
        model_name: Optional[str] = None,
        session_id: Optional[str] = None,
    ) -> InputCheckResult:
        """Check user input for injection or jailbreak attempts.

        Args:
            text: The raw user input to classify.
            model_provider: Optional provider for downstream model routing (e.g. "openai").
            model_name: Optional downstream model name (e.g. "gpt-5").
            session_id: Optional session identifier for event correlation.

        Returns:
            InputCheckResult with label, confidence, and latency.
        """
        body: dict[str, str] = {"text": text}
        if model_provider:
            body["model_provider"] = model_provider
        if model_name:
            body["model_name"] = model_name
        if session_id:
            body["session_id"] = session_id

        data = _post(_config.prompt_guard_url, body)
        return InputCheckResult(
            label=data["label"],
            confidence=data["confidence"],
            latency_ms=data["latency_ms"],
        )


class _ToolCall:
    """triage_sdk.tool_call.check(...) — evaluate tool-call safety."""

    @staticmethod
    def check(
        user_request: str,
        tool_name: str,
        tool_description: str = "",
        interaction_history: str = "",
        env_info: str = "",
        model_provider: Optional[str] = None,
        model_name: Optional[str] = None,
        session_id: Optional[str] = None,
    ) -> ToolCallCheckResult:
        """Check whether a tool call is safe to execute.

        Args:
            user_request: What the user asked the agent to do.
            tool_name: Name of the tool being invoked.
            tool_description: Description of the tool's capabilities.
            interaction_history: Prior conversation turns (optional).
            env_info: Environment context (optional).
            model_provider: Optional provider for downstream model routing (e.g. "openai").
            model_name: Optional downstream model name (e.g. "gpt-5").
            session_id: Optional session identifier for event correlation.

        Returns:
            ToolCallCheckResult with malicious, attacked, harmfulness, composite_score.
        """
        current_action = f"{tool_name}: {tool_description}" if tool_description else tool_name
        body: dict[str, str] = {
            "user_request": user_request,
            "interaction_history": interaction_history,
            "current_action": current_action,
            "env_info": env_info,
        }
        if model_provider:
            body["model_provider"] = model_provider
        if model_name:
            body["model_name"] = model_name
        if session_id:
            body["session_id"] = session_id

        data = _post(_config.tool_guard_url, body)
        return ToolCallCheckResult(
            malicious=data["malicious"],
            attacked=data["attacked"],
            harmfulness=data["harmfulness"],
            composite_score=data["composite_score"],
            latency_ms=data["latency_ms"],
        )


class _Output:
    """triage_sdk.output.check(text) — check agent output before sending to user."""

    @staticmethod
    def check(
        text: str,
        conversation_history: Optional[str] = None,
    ) -> OutputCheckResult:
        """Check the agent's final output before delivering to the user.

        NOTE: Not yet implemented — returns a safe stub.
        """
        return OutputCheckResult()


# ---------------------------------------------------------------------------
# Module-level singletons
# ---------------------------------------------------------------------------

input = _Input()
tool_call = _ToolCall()
output = _Output()
