"""
SOVR SDK Exceptions v3.0.0
Aligned with @sovr/sdk Node.js v3.0.0 error classes
"""

from typing import Optional, List, Dict, Any


class SOVRError(Exception):
    """Base exception for all SOVR SDK errors."""

    def __init__(
        self,
        message: str,
        status_code: Optional[int] = None,
        error_code: Optional[str] = None,
    ):
        super().__init__(message)
        self.message = message
        self.status_code = status_code or 500
        self.error_code = error_code or "INTERNAL_ERROR"

    def __str__(self) -> str:
        parts = [self.message]
        if self.status_code:
            parts.append(f"(HTTP {self.status_code})")
        if self.error_code:
            parts.append(f"[{self.error_code}]")
        return " ".join(parts)


class AuthenticationError(SOVRError):
    """Raised when API key is invalid or missing."""

    def __init__(self, message: str = "Authentication failed: invalid or missing API key"):
        super().__init__(message, status_code=401, error_code="UNAUTHORIZED")


class ForbiddenError(SOVRError):
    """Raised when the API key lacks required scope."""

    def __init__(self, message: str = "Insufficient scope for this operation"):
        super().__init__(message, status_code=403, error_code="INSUFFICIENT_SCOPE")


class NotFoundError(SOVRError):
    """Raised when the requested resource does not exist."""

    def __init__(self, message: str = "Resource not found"):
        super().__init__(message, status_code=404, error_code="NOT_FOUND")


class ValidationError(SOVRError):
    """Raised when request parameters fail validation."""

    def __init__(
        self,
        message: str = "Validation failed",
        errors: Optional[List[Dict[str, Any]]] = None,
    ):
        super().__init__(message, status_code=422, error_code="VALIDATION_ERROR")
        self.errors = errors or []

    def __str__(self) -> str:
        if self.errors:
            details = "; ".join(
                f"{e.get('field', 'unknown')}: {e.get('message', 'invalid')}"
                for e in self.errors
            )
            return f"{self.message}: {details}"
        return self.message


class RateLimitError(SOVRError):
    """Raised when request rate exceeds the limit."""

    def __init__(
        self,
        message: str = "Rate limit exceeded",
        retry_after: int = 60,
    ):
        super().__init__(message, status_code=429, error_code="RATE_LIMITED")
        self.retry_after = retry_after

    def __str__(self) -> str:
        return f"{self.message}. Retry after {self.retry_after}s."


class ActionBlockedError(SOVRError):
    """Raised when SOVR policy denies an action (via wrap/protect)."""

    def __init__(
        self,
        message: str = "Action blocked by SOVR policy",
        decision_id: Optional[str] = None,
    ):
        super().__init__(message, status_code=403, error_code="ACTION_BLOCKED")
        self.decision_id = decision_id


class ApprovalRequiredError(SOVRError):
    """Raised when an action requires human approval (via wrap/protect)."""

    def __init__(
        self,
        message: str = "Action requires human approval",
        decision_id: Optional[str] = None,
    ):
        super().__init__(message, status_code=403, error_code="APPROVAL_REQUIRED")
        self.decision_id = decision_id


class TimeoutError(SOVRError):
    """Raised when a request times out."""

    def __init__(self, message: str = "Request timeout", timeout: int = 30):
        super().__init__(message, error_code="TIMEOUT")
        self.timeout = timeout
