"""Pydantic models for UAPK Gateway SDK."""

from datetime import datetime
from enum import Enum
from typing import Any

from pydantic import BaseModel, Field


class GatewayDecision(str, Enum):
    """Gateway decision result."""

    ALLOW = "allow"
    DENY = "deny"
    ESCALATE = "escalate"


class ReasonCode(str, Enum):
    """Reason codes for gateway decisions."""

    # Allow
    POLICY_PASSED = "policy_passed"
    ALL_CHECKS_PASSED = "all_checks_passed"
    OVERRIDE_TOKEN_VALID = "override_token_valid"
    OVERRIDE_TOKEN_ACCEPTED = "override_token_accepted"
    # Deny
    MANIFEST_NOT_FOUND = "manifest_not_found"
    MANIFEST_NOT_ACTIVE = "manifest_not_active"
    ACTION_TYPE_NOT_ALLOWED = "action_type_not_allowed"
    TOOL_NOT_ALLOWED = "tool_not_allowed"
    AMOUNT_EXCEEDS_CAP = "amount_exceeds_cap"
    JURISDICTION_NOT_ALLOWED = "jurisdiction_not_allowed"
    COUNTERPARTY_DENIED = "counterparty_denied"
    COUNTERPARTY_NOT_IN_ALLOWLIST = "counterparty_not_in_allowlist"
    BUDGET_EXCEEDED = "budget_exceeded"
    HOURLY_BUDGET_EXCEEDED = "hourly_budget_exceeded"
    PER_ACTION_BUDGET_EXCEEDED = "per_action_budget_exceeded"
    OUTSIDE_TIME_WINDOW = "outside_time_window"
    CAPABILITY_NOT_GRANTED = "capability_not_granted"
    INVALID_REQUEST = "invalid_request"
    CAPABILITY_TOKEN_REQUIRED = "capability_token_required"
    CAPABILITY_TOKEN_INVALID = "capability_token_invalid"
    CAPABILITY_TOKEN_EXPIRED = "capability_token_expired"
    TOKEN_ISSUER_REVOKED = "token_issuer_revoked"
    TOKEN_AGENT_MISMATCH = "token_agent_mismatch"
    OVERRIDE_TOKEN_INVALID = "override_token_invalid"
    OVERRIDE_TOKEN_ALREADY_USED = "override_token_already_used"
    OVERRIDE_TOKEN_ACTION_MISMATCH = "override_token_action_mismatch"
    OVERRIDE_TOKEN_EXPIRED = "override_token_expired"
    # Escalate
    REQUIRES_HUMAN_APPROVAL = "requires_human_approval"
    AMOUNT_REQUIRES_APPROVAL = "amount_requires_approval"
    BUDGET_THRESHOLD_REACHED = "budget_threshold_reached"


class ActionInfo(BaseModel):
    """Information about the action being requested."""

    type: str = Field(..., description="Action type (e.g., 'refund', 'send_email')")
    tool: str = Field(..., description="Tool/connector to execute")
    params: dict[str, Any] = Field(default_factory=dict, description="Tool parameters")
    amount: float | None = Field(None, description="Transaction amount (if applicable)")
    currency: str | None = Field(None, description="Currency code (if applicable)")
    description: str | None = Field(None, description="Human-readable description")


class CounterpartyInfo(BaseModel):
    """Information about the counterparty (recipient/target)."""

    id: str | None = Field(None, description="Counterparty identifier")
    name: str | None = Field(None, description="Counterparty name")
    email: str | None = Field(None, description="Email address")
    domain: str | None = Field(None, description="Domain name")
    jurisdiction: str | None = Field(None, description="Jurisdiction/country code")


class ReasonDetail(BaseModel):
    """Detailed reason for a decision."""

    code: str  # str not enum — future-proof against new reason codes
    message: str
    details: dict[str, Any] | None = None


class GatewayActionRequest(BaseModel):
    """Request to evaluate or execute an action."""

    uapk_id: str = Field(..., description="UAPK manifest ID")
    agent_id: str = Field(..., description="Agent instance identifier")
    action: ActionInfo = Field(..., description="Action to perform")
    counterparty: CounterpartyInfo | None = Field(None, description="Counterparty information")
    context: dict[str, Any] = Field(default_factory=dict, description="Additional context")
    capability_token: str | None = Field(None, description="Capability token (if delegated)")
    override_token: str | None = Field(None, description="Override token from approval")


class GatewayDecisionResponse(BaseModel):
    """Response from evaluate endpoint."""

    interaction_id: str
    decision: GatewayDecision
    reasons: list[ReasonDetail]
    approval_id: str | None = None
    timestamp: datetime
    policy_version: str | None = None


class ToolResult(BaseModel):
    """Result from tool execution."""

    success: bool
    data: dict[str, Any] | None = None
    error: dict[str, Any] | None = None
    result_hash: str | None = None
    duration_ms: int | None = None


class GatewayExecuteResponse(BaseModel):
    """Response from execute endpoint."""

    interaction_id: str
    decision: GatewayDecision
    reasons: list[ReasonDetail]
    approval_id: str | None = None
    timestamp: datetime
    policy_version: str | None = None
    executed: bool
    result: ToolResult | None = None
