"""Exception hierarchy for llm-rotator."""

from __future__ import annotations

from datetime import datetime


class LLMRotatorError(Exception):
    """Base exception for llm-rotator."""


class KeyDeadError(LLMRotatorError):
    """Key is dead globally (401, 402, ban)."""

    def __init__(self, key_alias: str, status_code: int, message: str = "") -> None:
        self.key_alias = key_alias
        self.status_code = status_code
        super().__init__(message or f"Key '{key_alias}' is dead (HTTP {status_code})")


class ModelRateLimitError(LLMRotatorError):
    """Rate limit for a specific model on a specific key (429)."""

    def __init__(
        self, key_alias: str, model: str, retry_after: int | None = None
    ) -> None:
        self.key_alias = key_alias
        self.model = model
        self.retry_after = retry_after
        super().__init__(
            f"Rate limit for '{model}' on key '{key_alias}' (retry after {retry_after}s)"
        )


class ServerError(LLMRotatorError):
    """Provider server error (5xx)."""

    def __init__(self, provider: str, status_code: int, message: str = "") -> None:
        self.provider = provider
        self.status_code = status_code
        super().__init__(message or f"Server error from {provider} (HTTP {status_code})")


class QuotaExceededError(LLMRotatorError):
    """Local quota exhausted (tokens or requests)."""

    def __init__(
        self,
        scope: str,
        current: int,
        limit: int,
        resets_at: datetime | None = None,
    ) -> None:
        self.scope = scope
        self.current = current
        self.limit = limit
        self.resets_at = resets_at
        super().__init__(f"Quota exceeded for '{scope}': {current}/{limit}")


class AllAttemptsFailedError(ExceptionGroup):
    """All provider/model/key combinations exhausted."""

    def derive(self, excs: list[BaseException]) -> AllAttemptsFailedError:
        return AllAttemptsFailedError(self.message, excs)
