from typing import Any, Dict, Optional


class BackendError(Exception):
    status_code: int
    data: Dict[str, Any]

    def __init__(self, status_code: int, data: Dict[str, Any], log_message: Optional[str] = None):
        if "reason" not in data:
            data["reason"] = "unknown"
        if not log_message:
            log_message = f'BackendError {status_code}: {data["reason"]}'

        super().__init__(log_message)
        self.status_code = status_code
        self.data = data


class UnknownError(BackendError):
    def __init__(self, data: Dict[str, Any], log_message: Optional[str] = None):
        super().__init__(500, data, log_message)


class BadRequest(BackendError):
    def __init__(self, data: Dict[str, Any], log_message: Optional[str] = None):
        if "reason" not in data:
            data["reason"] = "bad_request"
        super().__init__(400, data, log_message)


class UnauthorizedError(BackendError):
    def __init__(self, data: Dict[str, Any], log_message: Optional[str] = None):
        super().__init__(403, data, log_message)


class NotFoundError(BackendError):
    def __init__(self, data: Dict[str, Any], log_message: Optional[str] = None):
        super().__init__(404, data, log_message)
