"""AllegoCore RPC wrappers — thin service layer (proto only)."""

from __future__ import annotations

from typing import TYPE_CHECKING

import grpc

from radiens_core._generated import allegoserver_pb2, allegoserver_pb2_grpc, common_pb2
from radiens_core._transport._errors import handle_grpc_error
from radiens_core.models.enums import ClientType

if TYPE_CHECKING:
    from radiens_core._transport._channel_pool import ChannelPool


def get_stim_params_proto(
    pool: ChannelPool,
    addr: str,
) -> allegoserver_pb2.StimParamsReply:
    """Send ``GetStimParams`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.GetStimParams(common_pb2.StandardRequest())
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def get_status_proto(
    pool: ChannelPool,
    addr: str,
) -> allegoserver_pb2.BackboneStatus:
    """Send ``GetStatus`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.GetStatus(common_pb2.StandardRequest())
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def set_stream_state_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.SetStreamRequest,
) -> common_pb2.StandardReply:
    """Send ``SetStreamState`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.SetStreamState(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def healthcheck_proto(
    pool: ChannelPool,
    addr: str,
) -> common_pb2.StandardReply:
    """Send ``Healthcheck`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoLifecycleStub(channel)
    try:
        return stub.Healthcheck(common_pb2.StandardRequest())
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def set_record_state_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.SetRecordRequest,
) -> common_pb2.StandardReply:
    """Send ``SetRecordState`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.SetRecordState(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def restart_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.RestartRequest,
) -> common_pb2.StandardReply:
    """Send ``Restart`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.Restart(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def set_stim_params_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.StimParams,
) -> common_pb2.StandardReply:
    """Send ``SetStimParams`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.SetStimParams(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def set_trigger_state_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.SetTriggerRequest,
) -> common_pb2.StandardReply:
    """Send ``SetTriggerState`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.SetTriggerState(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def get_trigger_state_proto(
    pool: ChannelPool,
    addr: str,
) -> allegoserver_pb2.TriggerState:
    """Send ``GetTriggerState`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.GetTriggerState(common_pb2.StandardRequest())
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def manual_stim_trigger_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.ManualStimTriggerRequest,
) -> common_pb2.StandardReply:
    """Send ``ManualStimTrigger`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.ManualStimTrigger(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def manual_stim_trigger_toggle_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.ManualStimTriggerToggleRequest,
) -> common_pb2.StandardReply:
    """Send ``ManualStimTriggerToggle`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.ManualStimTriggerToggle(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def set_stim_step_proto(
    pool: ChannelPool,
    addr: str,
    request: allegoserver_pb2.StimStepMessage,
) -> common_pb2.StandardReply:
    """Send ``SetStimStep`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.SetStimStep(request)
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy


def get_stim_step_proto(
    pool: ChannelPool,
    addr: str,
) -> allegoserver_pb2.StimStepMessage:
    """Send ``GetStimStep`` RPC, return raw proto response."""
    channel = pool.get_channel(addr)
    stub = allegoserver_pb2_grpc.AllegoCoreStub(channel)
    try:
        return stub.GetStimStep(common_pb2.StandardRequest())
    except grpc.RpcError as ex:
        handle_grpc_error(ex, ClientType.ALLEGO)
        raise  # unreachable, but satisfies mypy
