from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Literal

KnownErrorCode = Literal[
    "TEMPLATE_NOT_ENABLED_FOR_PROJECT",
    "ENVELOPE_NOT_FOUND",
    "BAD_PAGE_TOKEN",
    "BAD_SORT_FIELD",
    "FORBIDDEN",
    "BAD_JSON",
    "UPSTREAM_ERROR",
    "NOT_FOUND",
    "UNKNOWN_ERROR",
]

KNOWN_ERROR_CODES: tuple[str, ...] = (
    "TEMPLATE_NOT_ENABLED_FOR_PROJECT",
    "ENVELOPE_NOT_FOUND",
    "BAD_PAGE_TOKEN",
    "BAD_SORT_FIELD",
    "FORBIDDEN",
    "BAD_JSON",
    "UPSTREAM_ERROR",
    "NOT_FOUND",
    "UNKNOWN_ERROR",
)


@dataclass
class APIError(Exception):
    status: int
    message: str
    code: str | None = None
    request_id: str | None = None
    meta: dict[str, Any] | None = None
    raw_body: str = ""
    payload: dict[str, Any] | None = None

    def __str__(self) -> str:
        code = f" code={self.code}" if self.code else ""
        request_id = f" request_id={self.request_id}" if self.request_id else ""
        return f"status={self.status}{code}{request_id} message={self.message}"
