"""Exception hierarchy for LLM integration errors.

All LLM-related errors inherit from LLMError for easy catching.
Each exception includes actionable context in the message.
"""


class LLMError(Exception):
    """Base exception for all LLM-related errors."""

    pass


class RetryableError(LLMError):
    """Raised when an LLM call fails due to transient issues."""


class ProviderError(LLMError):
    """Raised when a provider cannot be initialized or is unknown.

    Common causes:
    - Unknown provider name in config
    - Missing API key for the provider
    - Provider package not installed
    """

    pass


class AuthenticationError(LLMError):
    """Raised when the LLM provider returns a 401 or 403 error.

    This indicates an invalid or expired API key. The user should
    check their API key configuration.
    """

    pass


class BriefingGenerationError(RetryableError):
    """Raised when briefing generation fails after retries.

    Includes the number of attempts made before failure.
    """

    def __init__(self, message: str, attempts: int = 1) -> None:
        self.attempts = attempts
        super().__init__(f"{message} (after {attempts} attempt(s))")


class MissionGenerationError(RetryableError):
    """Raised when mission generation fails for a specific category.

    Includes the category name and number of attempts made before failure.
    """

    def __init__(self, message: str, category: str = "", attempts: int = 1) -> None:
        self.category = category
        self.attempts = attempts
        detail = f"category '{category}'" if category else "mission generation"
        super().__init__(f"{message} ({detail}, after {attempts} attempt(s))")
