"""
LLM-specific exceptions.

Extends the MarkitectError hierarchy for LLM integration errors.
"""

from typing import Optional, Dict, Any

from markitect.exceptions import MarkitectError


class LLMError(MarkitectError):
    """Base exception for all LLM operations."""
    pass


class LLMConfigurationError(LLMError):
    """Missing API key, invalid model name, or bad provider config."""
    pass


class LLMAPIError(LLMError):
    """HTTP-level failure from an LLM provider API.

    Attributes:
        status_code: HTTP status code (e.g. 500, 502).
        response_body: Raw response body text, if available.
    """

    def __init__(
        self,
        message: str,
        status_code: int = 0,
        response_body: str = "",
        cause: Optional[Exception] = None,
        context: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, cause=cause, context=context)
        self.status_code = status_code
        self.response_body = response_body


class LLMRateLimitError(LLMAPIError):
    """429 Too Many Requests from the provider."""
    pass


class LLMTimeoutError(LLMError):
    """Request or subprocess exceeded the configured timeout."""
    pass


class LLMSubprocessError(LLMError):
    """Claude Code CLI subprocess failed.

    Attributes:
        return_code: Process exit code.
        stderr: Captured stderr text.
    """

    def __init__(
        self,
        message: str,
        return_code: int = 1,
        stderr: str = "",
        cause: Optional[Exception] = None,
        context: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, cause=cause, context=context)
        self.return_code = return_code
        self.stderr = stderr
