"""Pydantic models for wl-registry SDK.

Models mirror the Rust DTOs from the wl-registry service.
"""

from __future__ import annotations

from enum import Enum
from typing import Any

from pydantic import BaseModel, Field

# =============================================================================
# Enumerations
# =============================================================================


class TrustState(str, Enum):
    """Trust state for servers and agents."""

    UNVERIFIED = "unverified"
    TRUSTED = "trusted"
    QUARANTINED = "quarantined"
    REVOKED = "revoked"


class ServerStatus(str, Enum):
    """Server operational status."""

    ACTIVE = "active"
    INACTIVE = "inactive"


class AgentStatus(str, Enum):
    """Agent operational status."""

    ACTIVE = "active"
    INACTIVE = "inactive"
    SUSPENDED = "suspended"


class AgentType(str, Enum):
    """Type of AI agent."""

    ASSISTANT = "assistant"
    AUTONOMOUS = "autonomous"
    WORKFLOW = "workflow"
    TOOL_CALLING = "tool_calling"
    CUSTOM = "custom"


class TransportType(str, Enum):
    """MCP transport type."""

    STDIO = "stdio"
    STDIO_METADATA = "stdio_metadata"
    HTTP = "http"
    WS = "ws"
    UNIX_SOCKET = "unix_socket"


class CapabilityType(str, Enum):
    """Capability type (tool or resource)."""

    TOOL = "tool"
    RESOURCE = "resource"


# =============================================================================
# Server Models
# =============================================================================


class CapabilityInput(BaseModel):
    """Input for registering a server capability."""

    name: str
    version: str | None = None
    schema_: Any | None = Field(default=None, alias="schema")

    model_config = {"populate_by_name": True}


class RegisterServerRequest(BaseModel):
    """Request to register an MCP server."""

    host_id: str
    address: str
    transport: str
    metadata: dict[str, Any] | None = None
    lease_ttl_seconds: int = 60
    capabilities: list[CapabilityInput] = Field(default_factory=list)
    server_name: str | None = None
    server_version: str | None = None
    protocol_version: str | None = None
    schema_hash: str | None = None


class RegisterServerResponse(BaseModel):
    """Response from server registration."""

    server_id: str
    lease_expires_at: str
    trust_state: TrustState = TrustState.UNVERIFIED
    status: ServerStatus = ServerStatus.ACTIVE


class HeartbeatRequest(BaseModel):
    """Request to renew a server lease."""

    lease_ttl_seconds: int = 60


class HeartbeatResponse(BaseModel):
    """Response from server heartbeat."""

    server_id: str
    lease_expires_at: str


class UpdateTrustRequest(BaseModel):
    """Request to update trust state."""

    trust_state: TrustState
    reason: str | None = None


class UpdateTrustResponse(BaseModel):
    """Response from trust state update."""

    server_id: str | None = None
    agent_id: str | None = None
    trust_state: TrustState


class ServerListItem(BaseModel):
    """Server summary in list responses."""

    id: str
    instance_id: str | None = None
    host_id: str | None = None
    address: str | None = None
    transport: str | None = None
    trust_state: TrustState = TrustState.UNVERIFIED
    status: ServerStatus = ServerStatus.ACTIVE
    server_name: str | None = None
    server_version: str | None = None
    lease_expires_at: str | None = None
    discovered_at: str | None = None
    last_seen_at: str | None = None


class ServerDetail(BaseModel):
    """Detailed server information."""

    id: str
    instance_id: str | None = None
    scanner_id: str | None = None
    host_id: str | None = None
    address: str | None = None
    transport: str | None = None
    trust_state: TrustState = TrustState.UNVERIFIED
    status: ServerStatus = ServerStatus.ACTIVE
    server_name: str | None = None
    server_version: str | None = None
    protocol_version: str | None = None
    schema_hash: str | None = None
    metadata: dict[str, Any] | None = None
    lease_expires_at: str | None = None
    discovered_at: str | None = None
    last_seen_at: str | None = None
    capabilities: list[dict[str, Any]] = Field(default_factory=list)


class ListServersResponse(BaseModel):
    """Response for listing servers."""

    servers: list[ServerListItem] = Field(default_factory=list)
    next_cursor: str | None = None
    total: int = 0


# =============================================================================
# Agent Models
# =============================================================================


class SelfRegisterAgentRequest(BaseModel):
    """Request for agent self-registration."""

    name: str
    agent_type: AgentType = AgentType.ASSISTANT
    description: str | None = None
    version: str | None = None
    vendor: str | None = None
    capabilities: list[str] | None = None
    endpoint: str | None = None
    transport: str | None = None
    registration_token: str | None = None


class SelfRegisterAgentResponse(BaseModel):
    """Response from agent self-registration."""

    id: str
    agent_id: str | None = None
    name: str
    trust_state: TrustState = TrustState.UNVERIFIED
    api_key: str
    message: str = ""


class CreateAgentRequest(BaseModel):
    """Admin request to create an agent."""

    name: str
    agent_type: AgentType = AgentType.ASSISTANT
    description: str | None = None
    version: str | None = None
    vendor: str | None = None
    capabilities: list[str] | None = None
    endpoint: str | None = None
    transport: str | None = None
    allowed_intent_categories: list[str] | None = None
    max_trust_level: int | None = None


class CreateAgentResponse(BaseModel):
    """Response from admin agent creation."""

    agent_id: str
    name: str
    api_key: str


class UpdateAgentRequest(BaseModel):
    """Admin request to update an agent."""

    name: str | None = None
    description: str | None = None
    agent_type: AgentType | None = None
    version: str | None = None
    vendor: str | None = None
    capabilities: list[str] | None = None
    endpoint: str | None = None
    transport: str | None = None
    status: AgentStatus | None = None
    max_trust_level: int | None = None
    allowed_intent_categories: list[str] | None = None


class AgentListItem(BaseModel):
    """Agent summary in list responses."""

    id: str
    agent_id: str | None = None
    name: str
    description: str | None = None
    agent_type: AgentType = AgentType.ASSISTANT
    status: AgentStatus = AgentStatus.ACTIVE
    trust_state: TrustState = TrustState.UNVERIFIED
    version: str | None = None
    vendor: str | None = None
    discovered_at: str | None = None
    last_seen_at: str | None = None


class AgentDetail(BaseModel):
    """Detailed agent information."""

    id: str
    agent_id: str | None = None
    name: str
    description: str | None = None
    agent_type: AgentType = AgentType.ASSISTANT
    status: AgentStatus = AgentStatus.ACTIVE
    trust_state: TrustState = TrustState.UNVERIFIED
    version: str | None = None
    vendor: str | None = None
    capabilities: Any | None = None
    configuration: Any | None = None
    endpoint: str | None = None
    transport: str | None = None
    sponsor_id: str | None = None
    max_trust_level: int = 5
    allowed_intent_categories: list[str] = Field(default_factory=list)
    risk_signals: list[str] = Field(default_factory=list)
    discovered_at: str | None = None
    last_seen_at: str | None = None
    lease_expires_at: str | None = None
    created_at: str | None = None
    updated_at: str | None = None
    permissions: list[PermissionListItem] = Field(default_factory=list)


class ListAgentsResponse(BaseModel):
    """Response for listing agents."""

    agents: list[AgentListItem] = Field(default_factory=list)
    total: int = 0


class AgentStatsResponse(BaseModel):
    """Agent statistics."""

    total_agents: int = 0
    active_agents: int = 0
    trusted_agents: int = 0
    pending_approval: int = 0
    quarantined_agents: int = 0
    total_permissions: int = 0


class AccessibleServer(BaseModel):
    """Server accessible to an agent."""

    server_id: str
    server_name: str | None = None
    address: str
    transport: str
    server_trust_state: TrustState = TrustState.UNVERIFIED
    server_status: ServerStatus = ServerStatus.ACTIVE
    allowed_tools: Any | None = None
    allowed_resources: Any | None = None
    max_calls_per_session: int | None = None
    requires_intent: bool = False
    expires_at: str | None = None


class ListAccessibleServersResponse(BaseModel):
    """Response for listing agent's accessible servers."""

    servers: list[AccessibleServer] = Field(default_factory=list)
    total: int = 0


# =============================================================================
# Permission Models
# =============================================================================


class GrantPermissionRequest(BaseModel):
    """Request to grant agent permission to a server."""

    server_id: str
    allowed_tools: list[str] | None = None
    allowed_resources: list[str] | None = None
    max_calls_per_session: int | None = None
    requires_intent: bool | None = None
    expires_at: str | None = None


class PermissionListItem(BaseModel):
    """Permission entry."""

    id: str | None = None
    server_id: str
    server_name: str | None = None
    allowed_tools: Any | None = None
    allowed_resources: Any | None = None
    max_calls_per_session: int | None = None
    requires_intent: bool = False
    granted_by: str | None = None
    granted_at: str | None = None
    expires_at: str | None = None


class ListPermissionsResponse(BaseModel):
    """Response for listing permissions."""

    permissions: list[PermissionListItem] = Field(default_factory=list)
    total: int = 0


# =============================================================================
# Scanner Models
# =============================================================================


class CreateScannerRequest(BaseModel):
    """Request to create a scanner."""

    name: str
    description: str | None = None
    host_id: str | None = None


class CreateScannerResponse(BaseModel):
    """Response from scanner creation."""

    scanner_id: str
    name: str
    api_key: str


class ScannerListItem(BaseModel):
    """Scanner summary in list responses."""

    id: str
    name: str
    description: str | None = None
    host_id: str | None = None
    created_at: str | None = None
    last_seen_at: str | None = None


class ListScannersResponse(BaseModel):
    """Response for listing scanners."""

    scanners: list[ScannerListItem] = Field(default_factory=list)
    total: int = 0


class RotateKeyResponse(BaseModel):
    """Response from key rotation."""

    scanner_id: str | None = None
    agent_id: str | None = None
    api_key: str


# =============================================================================
# Registration Token Models
# =============================================================================


class CreateRegistrationTokenRequest(BaseModel):
    """Request to create a registration token."""

    name: str
    max_uses: int | None = None
    expires_in_hours: int | None = None


class RegistrationTokenResponse(BaseModel):
    """Response from token creation."""

    id: str
    name: str
    token: str
    max_uses: int | None = None
    expires_at: str | None = None


class RegistrationTokenListItem(BaseModel):
    """Token summary in list responses."""

    id: str
    name: str
    max_uses: int | None = None
    uses: int = 0
    expires_at: str | None = None
    created_at: str | None = None


class ListRegistrationTokensResponse(BaseModel):
    """Response for listing registration tokens."""

    tokens: list[RegistrationTokenListItem] = Field(default_factory=list)
    total: int = 0


# =============================================================================
# Registration Config
# =============================================================================


class RegistrationConfigResponse(BaseModel):
    """Response for registration configuration."""

    mode: str
    token_required: bool = False


# =============================================================================
# Health
# =============================================================================


class HealthResponse(BaseModel):
    """Health check response."""

    status: str
