from typing import Optional


class AppException(Exception):
    def __init__(
        self,
        message: str,
        status_code: int = 500,
        errors: Optional[list] = None,
        error_code: Optional[str] = None,
    ):
        self.message = message
        self.status_code = status_code
        self.errors = errors or []
        self.error_code = error_code
        super().__init__(self.message)


class NotFoundError(AppException):
    def __init__(self, message: str = "Resource not found"):
        super().__init__(message=message, status_code=404)


class UnauthorizedError(AppException):
    def __init__(self, message: str = "Authentication required"):
        super().__init__(message=message, status_code=401)


class ForbiddenError(AppException):
    def __init__(self, message: str = "Insufficient permissions", error_code: Optional[str] = None):
        super().__init__(message=message, status_code=403, error_code=error_code)


class ValidationError(AppException):
    def __init__(self, message: str = "Validation failed", errors: Optional[list] = None):
        super().__init__(message=message, status_code=422, errors=errors or [])


class ConflictError(AppException):
    def __init__(self, message: str = "Resource already exists"):
        super().__init__(message=message, status_code=409)


class TenantNotFoundError(AppException):
    def __init__(self, message: str = "Cemetery not found"):
        super().__init__(message=message, status_code=404)


class TenantSuspendedError(AppException):
    def __init__(self, message: str = "Account is suspended"):
        super().__init__(message=message, status_code=403)


class UnprocessableError(AppException):
    """HTTP 422 — business-rule transition violation."""
    def __init__(self, message: str = "Unprocessable request"):
        super().__init__(message=message, status_code=422)


class PaymentError(AppException):
    def __init__(self, message: str = "Payment failed. Please check your card details and try again."):
        super().__init__(message=message, status_code=402)


class RateLimitError(AppException):
    """HTTP 429 — too many requests. `retry_after` is seconds until the caller may retry."""
    def __init__(self, message: str = "Too many requests", retry_after: int = 60):
        super().__init__(message=message, status_code=429)
        self.retry_after = retry_after


class UnsupportedMediaTypeError(AppException):
    """HTTP 415 — the uploaded file's media type is not on the allowlist."""
    def __init__(self, message: str = "Unsupported media type"):
        super().__init__(message=message, status_code=415)


class PayloadTooLargeError(AppException):
    """HTTP 413 — the uploaded file exceeds the raw size cap."""
    def __init__(self, message: str = "Payload too large"):
        super().__init__(message=message, status_code=413)


class ServiceUnavailableError(AppException):
    """HTTP 503 — an upstream dependency (e.g. Google Geocoding) is unavailable."""
    def __init__(self, message: str = "Service temporarily unavailable"):
        super().__init__(message=message, status_code=503)
