"""gRPC status code -> domain exception mapping."""

from __future__ import annotations

from typing import TYPE_CHECKING

import grpc

from radiens_core.exceptions import (
    DataProcessingError,
    ServerCommunicationError,
)

if TYPE_CHECKING:
    from radiens_core.models.common import ClientType


def handle_grpc_error(ex: grpc.RpcError, client_type: ClientType) -> None:
    """Map a gRPC RpcError to a domain exception and raise it.

    Parameters
    ----------
    ex
        The gRPC error.
    client_type
        Client that encountered the error (for context in messages).

    Raises
    ------
    ServerCommunicationError
        For connectivity, auth, and unknown server errors.
    DataProcessingError
        For resource-exhausted errors.
    """
    status_code = ex.code()
    details = ex.details() or "No additional details"

    if status_code == grpc.StatusCode.UNAVAILABLE:
        raise ServerCommunicationError(
            f"Cannot connect to {client_type.value} server. Check that the application is running. Details: {details}"
        ) from None

    if status_code == grpc.StatusCode.UNAUTHENTICATED:
        raise ServerCommunicationError(
            f"Authentication failed for {client_type.value} server. Details: {details}"
        ) from None

    if status_code == grpc.StatusCode.RESOURCE_EXHAUSTED:
        raise DataProcessingError(
            f"Request too large for {client_type.value} server. Reduce time range or channel count. Details: {details}"
        ) from None

    if status_code == grpc.StatusCode.UNKNOWN:
        raise ServerCommunicationError(f"Unknown server error in {client_type.value}. Details: {details}") from None

    # Catch-all
    raise ServerCommunicationError(
        f"gRPC error with {client_type.value} server. Status: {status_code}. Details: {details}"
    ) from ex
