"""Tests for gRPC error mapping."""

import grpc
import pytest

from radiens_core._transport._errors import handle_grpc_error
from radiens_core.exceptions import DataProcessingError, ServerCommunicationError
from radiens_core.models.common import ClientType


class _FakeRpcError(grpc.RpcError):
    def __init__(self, status_code: grpc.StatusCode, details: str) -> None:
        self._status_code = status_code
        self._details = details

    def code(self) -> grpc.StatusCode:
        return self._status_code

    def details(self) -> str:
        return self._details


def _make_rpc_error(status_code: grpc.StatusCode, details: str = "test") -> grpc.RpcError:
    return _FakeRpcError(status_code, details)


def test_unavailable_maps_to_server_error() -> None:
    ex = _make_rpc_error(grpc.StatusCode.UNAVAILABLE)
    with pytest.raises(ServerCommunicationError, match="Cannot connect"):
        handle_grpc_error(ex, ClientType.VIDERE)


def test_unauthenticated_maps_to_server_error() -> None:
    ex = _make_rpc_error(grpc.StatusCode.UNAUTHENTICATED)
    with pytest.raises(ServerCommunicationError, match="Authentication failed"):
        handle_grpc_error(ex, ClientType.ALLEGO)


def test_resource_exhausted_maps_to_data_error() -> None:
    ex = _make_rpc_error(grpc.StatusCode.RESOURCE_EXHAUSTED)
    with pytest.raises(DataProcessingError, match="too large"):
        handle_grpc_error(ex, ClientType.VIDERE)


def test_unknown_maps_to_server_error() -> None:
    ex = _make_rpc_error(grpc.StatusCode.UNKNOWN)
    with pytest.raises(ServerCommunicationError, match="Unknown"):
        handle_grpc_error(ex, ClientType.CURATE)


def test_other_status_maps_to_server_error() -> None:
    ex = _make_rpc_error(grpc.StatusCode.INTERNAL)
    with pytest.raises(ServerCommunicationError, match="gRPC error"):
        handle_grpc_error(ex, ClientType.VIDERE)
