"""Exceptions for the Vaikora SDK."""
from typing import Any, Optional


class VaikoraError(Exception):
    """Base exception for all Vaikora errors."""
    
    def __init__(
        self,
        message: str,
        status_code: Optional[int] = None,
        response_data: Optional[dict[str, Any]] = None,
    ):
        super().__init__(message)
        self.message = message
        self.status_code = status_code
        self.response_data = response_data or {}

    def __str__(self) -> str:
        if self.status_code:
            return f"[{self.status_code}] {self.message}"
        return self.message


class AuthenticationError(VaikoraError):
    """Raised when authentication fails (invalid API key, expired token, etc.)."""
    pass


class AuthorizationError(VaikoraError):
    """Raised when the user doesn't have permission to perform an action."""
    pass


class RateLimitError(VaikoraError):
    """Raised when rate limit is exceeded."""
    
    def __init__(
        self,
        message: str,
        retry_after: Optional[int] = None,
        **kwargs: Any,
    ):
        super().__init__(message, **kwargs)
        self.retry_after = retry_after


class PolicyViolationError(VaikoraError):
    """Raised when an action violates a security policy."""
    
    def __init__(
        self,
        message: str,
        policy_id: Optional[str] = None,
        policy_name: Optional[str] = None,
        **kwargs: Any,
    ):
        super().__init__(message, **kwargs)
        self.policy_id = policy_id
        self.policy_name = policy_name


class NetworkError(VaikoraError):
    """Raised when there's a network-related error."""
    pass


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


class ValidationError(VaikoraError):
    """Raised when request validation fails."""
    
    def __init__(
        self,
        message: str,
        errors: Optional[list[dict[str, Any]]] = None,
        **kwargs: Any,
    ):
        super().__init__(message, **kwargs)
        self.errors = errors or []


class NotFoundError(VaikoraError):
    """Raised when a requested resource is not found."""
    pass


class ConflictError(VaikoraError):
    """Raised when there's a conflict (e.g., duplicate resource)."""
    pass


class ServerError(VaikoraError):
    """Raised when the server returns a 5xx error."""
    pass


def raise_for_status(status_code: int, response_data: dict[str, Any]) -> None:
    """Raise appropriate exception based on status code."""
    message = response_data.get("detail", response_data.get("message", "Unknown error"))
    
    if status_code == 401:
        raise AuthenticationError(message, status_code, response_data)
    elif status_code == 403:
        raise AuthorizationError(message, status_code, response_data)
    elif status_code == 404:
        raise NotFoundError(message, status_code, response_data)
    elif status_code == 409:
        raise ConflictError(message, status_code, response_data)
    elif status_code == 422:
        errors = response_data.get("errors", response_data.get("detail", []))
        if isinstance(errors, str):
            errors = [{"msg": errors}]
        raise ValidationError(message, errors=errors, status_code=status_code, response_data=response_data)
    elif status_code == 429:
        retry_after = response_data.get("retry_after")
        raise RateLimitError(message, retry_after=retry_after, status_code=status_code, response_data=response_data)
    elif 400 <= status_code < 500:
        # Check for policy violation
        if "policy" in message.lower() or response_data.get("policy_id"):
            raise PolicyViolationError(
                message,
                policy_id=response_data.get("policy_id"),
                policy_name=response_data.get("policy_name"),
                status_code=status_code,
                response_data=response_data,
            )
        raise VaikoraError(message, status_code, response_data)
    elif status_code >= 500:
        raise ServerError(message, status_code, response_data)
