"""
Type definitions for the SentryAgent.ai AgentIdP Python SDK.
All request and response shapes derived from the AgentIdP OpenAPI 3.0 specs.
"""

from __future__ import annotations

from typing import Any, Dict, List, Literal, Optional
from dataclasses import dataclass, field

# ─────────────────────────────────────────────────────────────────────────────
# Enums / Literal types
# ─────────────────────────────────────────────────────────────────────────────

AgentType = Literal[
    "screener",
    "classifier",
    "orchestrator",
    "extractor",
    "summarizer",
    "router",
    "monitor",
    "custom",
]

AgentStatus = Literal["active", "suspended", "decommissioned"]

DeploymentEnv = Literal["development", "staging", "production"]

CredentialStatus = Literal["active", "revoked"]

OAuthScope = Literal["agents:read", "agents:write", "tokens:read", "audit:read"]

AuditAction = Literal[
    "agent.created",
    "agent.updated",
    "agent.decommissioned",
    "agent.suspended",
    "agent.reactivated",
    "token.issued",
    "token.revoked",
    "token.introspected",
    "credential.generated",
    "credential.rotated",
    "credential.revoked",
    "auth.failed",
]

AuditOutcome = Literal["success", "failure"]

# ─────────────────────────────────────────────────────────────────────────────
# Agent Registry
# ─────────────────────────────────────────────────────────────────────────────


@dataclass
class Agent:
    """A registered AI agent identity."""

    agent_id: str
    email: str
    agent_type: AgentType
    version: str
    capabilities: List[str]
    owner: str
    deployment_env: DeploymentEnv
    status: AgentStatus
    created_at: str
    updated_at: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Agent":
        """Deserialise from an API response dict."""
        return cls(
            agent_id=data["agentId"],
            email=data["email"],
            agent_type=data["agentType"],
            version=data["version"],
            capabilities=data["capabilities"],
            owner=data["owner"],
            deployment_env=data["deploymentEnv"],
            status=data["status"],
            created_at=data["createdAt"],
            updated_at=data["updatedAt"],
        )


@dataclass
class RegisterAgentRequest:
    """Request body for registering a new AI agent."""

    email: str
    agent_type: AgentType
    version: str
    capabilities: List[str]
    owner: str
    deployment_env: DeploymentEnv

    def to_dict(self) -> Dict[str, Any]:
        """Serialise to API request dict."""
        return {
            "email": self.email,
            "agentType": self.agent_type,
            "version": self.version,
            "capabilities": self.capabilities,
            "owner": self.owner,
            "deploymentEnv": self.deployment_env,
        }


@dataclass
class UpdateAgentRequest:
    """Request body for partially updating an agent (all fields optional)."""

    agent_type: Optional[AgentType] = None
    version: Optional[str] = None
    capabilities: Optional[List[str]] = None
    owner: Optional[str] = None
    deployment_env: Optional[DeploymentEnv] = None
    status: Optional[AgentStatus] = None

    def to_dict(self) -> Dict[str, Any]:
        """Serialise to API request dict, omitting None fields."""
        out: Dict[str, Any] = {}
        if self.agent_type is not None:
            out["agentType"] = self.agent_type
        if self.version is not None:
            out["version"] = self.version
        if self.capabilities is not None:
            out["capabilities"] = self.capabilities
        if self.owner is not None:
            out["owner"] = self.owner
        if self.deployment_env is not None:
            out["deploymentEnv"] = self.deployment_env
        if self.status is not None:
            out["status"] = self.status
        return out


@dataclass
class PaginatedAgents:
    """Paginated list of agents."""

    data: List[Agent]
    total: int
    page: int
    limit: int

    @classmethod
    def from_dict(cls, d: Dict[str, Any]) -> "PaginatedAgents":
        return cls(
            data=[Agent.from_dict(a) for a in d["data"]],
            total=d["total"],
            page=d["page"],
            limit=d["limit"],
        )


# ─────────────────────────────────────────────────────────────────────────────
# Credential Management
# ─────────────────────────────────────────────────────────────────────────────


@dataclass
class Credential:
    """A credential record (client_secret never included)."""

    credential_id: str
    client_id: str
    status: CredentialStatus
    created_at: str
    expires_at: Optional[str]
    revoked_at: Optional[str]

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Credential":
        return cls(
            credential_id=data["credentialId"],
            client_id=data["clientId"],
            status=data["status"],
            created_at=data["createdAt"],
            expires_at=data.get("expiresAt"),
            revoked_at=data.get("revokedAt"),
        )


@dataclass
class CredentialWithSecret(Credential):
    """Credential with plain-text secret — returned once only on create/rotate."""

    client_secret: str = field(default="")

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "CredentialWithSecret":
        base = Credential.from_dict(data)
        return cls(
            credential_id=base.credential_id,
            client_id=base.client_id,
            status=base.status,
            created_at=base.created_at,
            expires_at=base.expires_at,
            revoked_at=base.revoked_at,
            client_secret=data["clientSecret"],
        )


@dataclass
class PaginatedCredentials:
    """Paginated list of credentials."""

    data: List[Credential]
    total: int
    page: int
    limit: int

    @classmethod
    def from_dict(cls, d: Dict[str, Any]) -> "PaginatedCredentials":
        return cls(
            data=[Credential.from_dict(c) for c in d["data"]],
            total=d["total"],
            page=d["page"],
            limit=d["limit"],
        )


# ─────────────────────────────────────────────────────────────────────────────
# OAuth 2.0 Tokens
# ─────────────────────────────────────────────────────────────────────────────


@dataclass
class TokenResponse:
    """OAuth 2.0 access token response."""

    access_token: str
    token_type: str
    expires_in: int
    scope: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "TokenResponse":
        return cls(
            access_token=data["access_token"],
            token_type=data["token_type"],
            expires_in=data["expires_in"],
            scope=data["scope"],
        )


@dataclass
class IntrospectResponse:
    """Token introspection response (RFC 7662)."""

    active: bool
    sub: Optional[str] = None
    client_id: Optional[str] = None
    scope: Optional[str] = None
    token_type: Optional[str] = None
    iat: Optional[int] = None
    exp: Optional[int] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "IntrospectResponse":
        return cls(
            active=data["active"],
            sub=data.get("sub"),
            client_id=data.get("client_id"),
            scope=data.get("scope"),
            token_type=data.get("token_type"),
            iat=data.get("iat"),
            exp=data.get("exp"),
        )


# ─────────────────────────────────────────────────────────────────────────────
# Audit Log
# ─────────────────────────────────────────────────────────────────────────────


@dataclass
class AuditEvent:
    """An immutable audit event record."""

    event_id: str
    agent_id: str
    action: AuditAction
    outcome: AuditOutcome
    ip_address: str
    user_agent: str
    metadata: Dict[str, Any]
    timestamp: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "AuditEvent":
        return cls(
            event_id=data["eventId"],
            agent_id=data["agentId"],
            action=data["action"],
            outcome=data["outcome"],
            ip_address=data["ipAddress"],
            user_agent=data["userAgent"],
            metadata=data.get("metadata", {}),
            timestamp=data["timestamp"],
        )


@dataclass
class PaginatedAuditEvents:
    """Paginated list of audit events."""

    data: List[AuditEvent]
    total: int
    page: int
    limit: int

    @classmethod
    def from_dict(cls, d: Dict[str, Any]) -> "PaginatedAuditEvents":
        return cls(
            data=[AuditEvent.from_dict(e) for e in d["data"]],
            total=d["total"],
            page=d["page"],
            limit=d["limit"],
        )
