class VerlexError(Exception):
    pass


class AuthenticationError(VerlexError):
    pass


class NotAuthenticatedError(AuthenticationError):
    pass


class InvalidAPIKeyError(AuthenticationError):
    pass


class ExecutionError(VerlexError):
    pass


class JobFailedError(ExecutionError):
    def __init__(self, job_id: str, message: str, logs: str = ""):
        self.job_id = job_id
        self.logs = logs
        super().__init__(f"Job {job_id} failed: {message}")


class JobTimeoutError(ExecutionError):
    def __init__(self, job_id: str, timeout_seconds: int):
        self.job_id = job_id
        self.timeout_seconds = timeout_seconds
        super().__init__(f"Job {job_id} timed out after {timeout_seconds} seconds")


class SerializationError(VerlexError):
    pass


class NetworkError(VerlexError):
    pass


class RateLimitError(VerlexError):
    def __init__(self, retry_after: int | None = 60):
        self.retry_after = retry_after
        if retry_after:
            super().__init__(f"Rate limit exceeded. Retry after {retry_after} seconds.")
        else:
            super().__init__("Rate limit exceeded.")


class InsufficientCreditsError(VerlexError):
    def __init__(self, required: float, available: float):
        self.required = required
        self.available = available
        super().__init__(
            f"Insufficient credits: need ${required:.2f}, have ${available:.2f}. "
            f"Add credits at https://verlex.dev/billing"
        )


class QuotaExceededError(VerlexError):
    pass


class GPUUnavailableError(VerlexError):
    def __init__(self, gpu_type: str, available_types: list = None):
        self.gpu_type = gpu_type
        self.available_types = available_types or []
        msg = f"GPU type '{gpu_type}' is not available"
        if self.available_types:
            msg += f". Available: {', '.join(self.available_types)}"
        super().__init__(msg)


class ConfigurationError(VerlexError):
    pass
