from __future__ import annotations

"""Nexure SDK exception hierarchy.

NexureError
├── AuthenticationError     (401)
├── ValidationError         (422)
├── RateLimitError          (429)
├── NotFoundError           (404)
└── ServerError             (500)
"""

import contextlib
from typing import Any


class NexureError(Exception):
    """Base exception for all Nexure SDK errors."""

    def __init__(
        self, message: str, status_code: int | None = None, body: dict[str, Any] | None = None
    ):
        self.message = message
        self.status_code = status_code
        self.body = body or {}
        super().__init__(message)


class AuthenticationError(NexureError):
    """401 — Invalid or missing API key."""

    pass


class ValidationError(NexureError):
    """422 — Request validation failed."""

    pass


class RateLimitError(NexureError):
    """429 — Rate limit exceeded."""

    def __init__(self, message: str, retry_after: float | None = None, **kwargs: Any):
        super().__init__(message, status_code=429, **kwargs)
        self.retry_after = retry_after


class NotFoundError(NexureError):
    """404 — Resource not found."""

    pass


class ServerError(NexureError):
    """500 — Internal server error."""

    pass


def _handle_response(
    status_code: int, body: dict[str, Any], headers: dict[str, str] | None = None
) -> None:
    """Raise the appropriate exception for non-2xx responses."""
    if 200 <= status_code < 300:
        return

    error_body = body.get("error", body.get("detail", {}))
    if isinstance(error_body, dict):
        message = error_body.get("message", str(body))
    elif isinstance(error_body, list):
        # FastAPI validation errors return a list
        message = str(error_body)
    else:
        message = str(error_body)

    if status_code == 401:
        raise AuthenticationError(message, status_code=401, body=body)
    elif status_code == 404:
        raise NotFoundError(message, status_code=404, body=body)
    elif status_code == 422:
        raise ValidationError(message, status_code=422, body=body)
    elif status_code == 429:
        retry_after = None
        if headers:
            ra = headers.get("retry-after") or headers.get("x-ratelimit-reset")
            if ra:
                with contextlib.suppress(ValueError):
                    retry_after = float(ra)
        raise RateLimitError(message, retry_after=retry_after, body=body)
    elif status_code >= 500:
        raise ServerError(message, status_code=status_code, body=body)
    else:
        raise NexureError(message, status_code=status_code, body=body)
