"""
Custom exception classes for the RLM system.

These exceptions provide better error handling and debugging capabilities
throughout the RLM pipeline.
"""


class RLMError(Exception):
    """Base exception for all RLM-related errors."""

    pass


class REPLExecutionError(RLMError):
    """Raised when code execution in the REPL environment fails."""

    def __init__(self, message: str, code: str | None = None, stderr: str | None = None):
        """Initialize REPLExecutionError.

        Args:
            message: Human-readable error message
            code: The code that failed to execute
            stderr: Standard error output from the execution
        """
        super().__init__(message)
        self.code = code
        self.stderr = stderr


class LMHandlerError(RLMError):
    """Base exception for LM handler-related errors."""

    pass


class LMHandlerTimeoutError(LMHandlerError):
    """Raised when an LM handler request times out."""

    def __init__(self, message: str, timeout_seconds: float | None = None):
        """Initialize LMHandlerTimeoutError.

        Args:
            message: Human-readable error message
            timeout_seconds: The timeout value that was exceeded
        """
        super().__init__(message)
        self.timeout_seconds = timeout_seconds


class LMHandlerConnectionError(LMHandlerError):
    """Raised when connection to LM handler fails."""

    pass


class ContextError(RLMError):
    """Base exception for context-related errors."""

    pass


class ContextTooLargeError(ContextError):
    """Raised when context exceeds reasonable size limits."""

    def __init__(self, message: str, context_size: int | None = None, max_size: int | None = None):
        """Initialize ContextTooLargeError.

        Args:
            message: Human-readable error message
            context_size: Actual size of the context
            max_size: Maximum allowed context size
        """
        super().__init__(message)
        self.context_size = context_size
        self.max_size = max_size


class CostLimitExceededError(RLMError):
    """Raised when cost limits are exceeded during RLM execution."""

    def __init__(
        self,
        message: str,
        current_cost: float | None = None,
        cost_limit: float | None = None,
    ):
        """Initialize CostLimitExceededError.

        Args:
            message: Human-readable error message
            current_cost: Current accumulated cost
            cost_limit: Maximum allowed cost
        """
        super().__init__(message)
        self.current_cost = current_cost
        self.cost_limit = cost_limit


class IterationLimitExceededError(RLMError):
    """Raised when maximum iterations are exceeded."""

    def __init__(
        self, message: str, max_iterations: int | None = None, current_iteration: int | None = None
    ):
        """Initialize IterationLimitExceededError.

        Args:
            message: Human-readable error message
            max_iterations: Maximum allowed iterations
            current_iteration: Current iteration number
        """
        super().__init__(message)
        self.max_iterations = max_iterations
        self.current_iteration = current_iteration


class CompletionTimeoutError(RLMError):
    """Raised when a completion times out."""

    def __init__(
        self,
        message: str,
        timeout_seconds: float | None = None,
        elapsed_seconds: float | None = None,
    ):
        """Initialize CompletionTimeoutError.

        Args:
            message: Human-readable error message
            timeout_seconds: Configured timeout value
            elapsed_seconds: Time elapsed before timeout
        """
        super().__init__(message)
        self.timeout_seconds = timeout_seconds
        self.elapsed_seconds = elapsed_seconds


class EnvironmentError(RLMError):
    """Base exception for environment-related errors."""

    pass


class EnvironmentSetupError(EnvironmentError):
    """Raised when environment setup fails."""

    pass


class EnvironmentCleanupError(EnvironmentError):
    """Raised when environment cleanup fails."""

    pass


class ParsingError(RLMError):
    """Raised when parsing RLM responses fails."""

    def __init__(self, message: str, response_text: str | None = None):
        """Initialize ParsingError.

        Args:
            message: Human-readable error message
            response_text: The response text that failed to parse
        """
        super().__init__(message)
        self.response_text = response_text


class FinalAnswerNotFoundError(ParsingError):
    """Raised when no final answer is found after max iterations."""

    def __init__(self, message: str, iterations_completed: int | None = None):
        """Initialize FinalAnswerNotFoundError.

        Args:
            message: Human-readable error message
            iterations_completed: Number of iterations that were completed
        """
        super().__init__(message)
        self.iterations_completed = iterations_completed
