# exceptions.py
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Optional


class LayBotError(Exception):
    """Base of all SDK errors"""


class ValidationError(LayBotError):
    """Invalid or missing parameter"""


@dataclass
class HttpError(LayBotError):
    """
    Generic HTTP error (status >= 400) with context.
    """
    status_code: int
    message: str = ""
    url: str = ""
    raw: Any = None

    def __str__(self) -> str:
        base = f"HTTP {self.status_code}"
        if self.message:
            base += f": {self.message}"
        if self.url:
            base += f" ({self.url})"
        return base


# ----- LayBot 中台业务错误（按 error_codes 表） -----

@dataclass
class LayBotApiError(HttpError):
    """
    LayBot API business error.
    - code: 业务码（如 40101）
    - err: 业务短码（如 API_KEY_INVALID）
    - request_id: 方便后端排障（如果中台有回）
    """
    code: Optional[int] = None
    err: str = ""
    request_id: str = ""

    def __str__(self) -> str:
        parts = [f"HTTP {self.status_code}"]
        if self.code is not None:
            parts.append(f"code={self.code}")
        if self.err:
            parts.append(f"err={self.err}")
        if self.message:
            parts.append(f"msg={self.message}")
        if self.request_id:
            parts.append(f"rid={self.request_id}")
        if self.url:
            parts.append(f"url={self.url}")
        return " | ".join(parts)


# 语义化子类（方便业务捕获）
class ModelNotAllowedError(LayBotApiError): ...
class ParamInvalidError(LayBotApiError): ...
class FunctionUnsupportedError(LayBotApiError): ...
class CapabilityForbiddenError(LayBotApiError): ...
class DuplicateRequestError(LayBotApiError): ...
class ApiKeyInvalidError(LayBotApiError): ...
class IpNotAllowedError(LayBotApiError): ...
class InsufficientCreditError(LayBotApiError): ...
class PayloadTooLargeError(LayBotApiError): ...
class UnsupportedMediaTypeError(LayBotApiError): ...
class JobNotFinishedError(LayBotApiError): ...
class RateLimitedError(LayBotApiError): ...
class InternalError(LayBotApiError): ...
class DependencyError(LayBotApiError): ...
class UpstreamTimeoutError(LayBotApiError): ...
class ServiceUnavailableError(LayBotApiError): ...
class MaintenanceModeError(LayBotApiError): ...


# 保留你原来的语义类名（兼容旧代码捕获）
CreditError = InsufficientCreditError
RateLimitError = RateLimitedError
FileError = LayBotError
RuntimeError = LayBotError
