"""Exception classes for wl-apdp SDK."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from .models import AuthorizationResponse


class WlApdpError(Exception):
    """Base exception for wl-apdp SDK."""

    pass


class AuthorizationDenied(WlApdpError):
    """Raised when authorization is denied.

    Attributes:
        response: The full authorization response from the server.
        principal: The principal that was denied access.
        action: The action that was attempted.
        resource: The resource that access was denied to.
    """

    def __init__(
        self,
        message: str,
        response: AuthorizationResponse | None = None,
        principal: str | None = None,
        action: str | None = None,
        resource: str | None = None,
    ) -> None:
        super().__init__(message)
        self.response = response
        self.principal = principal
        self.action = action
        self.resource = resource

    def __str__(self) -> str:
        parts = [super().__str__()]
        if self.principal:
            parts.append(f"principal={self.principal}")
        if self.action:
            parts.append(f"action={self.action}")
        if self.resource:
            parts.append(f"resource={self.resource}")
        return " | ".join(parts)


class ServiceUnavailable(WlApdpError):
    """Raised when wl-apdp service is unavailable."""

    def __init__(
        self,
        message: str = "WL-APDP service is unavailable",
        url: str | None = None,
    ) -> None:
        super().__init__(message)
        self.url = url


class ConfigurationError(WlApdpError):
    """Raised when there's a configuration error."""

    pass


class ValidationError(WlApdpError):
    """Raised when request validation fails."""

    def __init__(self, message: str, errors: list[dict[str, Any]] | None = None) -> None:
        super().__init__(message)
        self.errors = errors or []


class TokenError(WlApdpError):
    """Raised when there's an authentication token error."""

    pass


# =============================================================================
# Trust-Related Exceptions
# =============================================================================
# These exceptions are raised when an agent's trust state prevents access
# to the guidance layer (constraint manifests, pre-flight checks, etc.)


class AgentTrustError(WlApdpError):
    """Base exception for agent trust-related errors.

    Attributes:
        agent_id: The ID of the agent.
        trust_state: The current trust state of the agent.
    """

    def __init__(
        self,
        message: str,
        agent_id: str | None = None,
        trust_state: str | None = None,
    ) -> None:
        super().__init__(message)
        self.agent_id = agent_id
        self.trust_state = trust_state

    def __str__(self) -> str:
        parts = [super().__str__()]
        if self.agent_id:
            parts.append(f"agent_id={self.agent_id}")
        if self.trust_state:
            parts.append(f"trust_state={self.trust_state}")
        return " | ".join(parts)


class AgentTrustRevoked(AgentTrustError):
    """Raised when an agent's trust has been revoked.

    Agents with revoked trust cannot access constraint manifests or perform
    pre-flight checks. The agent must be re-approved by an administrator.

    Attributes:
        agent_id: The ID of the agent whose trust was revoked.
    """

    def __init__(
        self,
        message: str = "Agent trust has been revoked",
        agent_id: str | None = None,
    ) -> None:
        super().__init__(message, agent_id=agent_id, trust_state="revoked")


class AgentQuarantined(AgentTrustError):
    """Raised when an agent is quarantined.

    Quarantined agents receive restricted manifests with minimal capabilities.
    Pre-flight checks are denied. The agent is under investigation.

    Attributes:
        agent_id: The ID of the quarantined agent.
    """

    def __init__(
        self,
        message: str = "Agent is quarantined",
        agent_id: str | None = None,
    ) -> None:
        super().__init__(message, agent_id=agent_id, trust_state="quarantined")


class AgentUnverified(AgentTrustError):
    """Raised when an agent has not been verified.

    Unverified agents receive limited manifests with no capabilities disclosed.
    Pre-flight checks are denied. The agent must complete the trust verification
    process before accessing guidance.

    Attributes:
        agent_id: The ID of the unverified agent.
    """

    def __init__(
        self,
        message: str = "Agent has not been verified",
        agent_id: str | None = None,
    ) -> None:
        super().__init__(message, agent_id=agent_id, trust_state="unverified")
