#!/usr/bin/env python3
"""
GENESIS QWEN EXCEPTIONS
========================
Custom exceptions for the unified Qwen integration.

Hierarchy:
    QwenError (base)
    ├── QwenConnectionError - Network/endpoint issues
    ├── QwenTimeoutError - Request timeout
    ├── QwenModelNotFoundError - Model not loaded in Ollama
    ├── QwenRateLimitError - Rate limit exceeded
    ├── QwenCircuitOpenError - Circuit breaker is open
    └── QwenResponseError - Invalid/unexpected response

Usage:
    from core.qwen.exceptions import QwenConnectionError

    try:
        response = client.generate(prompt)
    except QwenConnectionError as e:
        logger.error(f"Cannot reach AIVA Ollama: {e}")
"""


class QwenError(Exception):
    """Base exception for all Qwen-related errors."""

    def __init__(self, message: str, details: dict = None):
        super().__init__(message)
        self.message = message
        self.details = details or {}

    def __str__(self) -> str:
        if self.details:
            return f"{self.message} | Details: {self.details}"
        return self.message


class QwenConnectionError(QwenError):
    """
    Raised when connection to Qwen/Ollama endpoint fails.

    Common causes:
    - AIVA server unreachable
    - Wrong port (use 23405, NOT 11434)
    - Firewall blocking connection
    - Ollama service not running
    """
    pass


class QwenTimeoutError(QwenError):
    """
    Raised when request times out.

    Common causes:
    - Model cold start (first request after idle)
    - Very long context (>32k tokens)
    - Server overloaded
    """
    pass


class QwenModelNotFoundError(QwenError):
    """
    Raised when the specified model is not loaded in Ollama.

    Expected model: huihui_ai/qwenlong-l1.5-abliterated:30b-a3b

    This should NOT happen in production as AIVA's Ollama
    has a single model that stays loaded.
    """
    pass


class QwenRateLimitError(QwenError):
    """
    Raised when rate limit is exceeded.

    The QwenRateMaximizer should prevent this by queuing
    requests, but this exception handles edge cases.
    """

    def __init__(self, message: str, retry_after: float = None, details: dict = None):
        super().__init__(message, details)
        self.retry_after = retry_after


class QwenCircuitOpenError(QwenError):
    """
    Raised when circuit breaker is open (too many failures).

    The system will automatically attempt recovery after
    the recovery timeout (default 60 seconds).
    """

    def __init__(self, message: str, recovery_time: float = None, details: dict = None):
        super().__init__(message, details)
        self.recovery_time = recovery_time


class QwenResponseError(QwenError):
    """
    Raised when response is invalid or unexpected.

    Common causes:
    - Malformed JSON response
    - Missing expected fields
    - Empty response
    - Model error in response
    """
    pass


class QwenWarmupError(QwenError):
    """
    Raised when model warmup fails.

    The model warmer periodically pings the model to keep it
    loaded. If warmup fails repeatedly, this exception is raised.
    """
    pass


# VERIFICATION_STAMP
# Story: STORY-001
# Verified By: CLAUDE
# Verified At: 2026-01-22
# Tests: Pending
# Coverage: Pending
