"""OTLP gRPC receiver for otelctx — traces, logs, and metrics."""

from __future__ import annotations

from concurrent import futures
from typing import Any


def start_otlp_grpc_server(port: int, ingest_callback):
    """Start an OTLP gRPC server handling traces, logs, and metrics.

    Returns a started grpc.Server instance.
    Raises RuntimeError when grpc/proto dependencies are unavailable.
    """
    try:
        import grpc
        from google.protobuf.json_format import MessageToDict
        from opentelemetry.proto.collector.logs.v1 import logs_service_pb2_grpc
        from opentelemetry.proto.collector.logs.v1.logs_service_pb2 import ExportLogsServiceResponse
        from opentelemetry.proto.collector.metrics.v1 import metrics_service_pb2_grpc
        from opentelemetry.proto.collector.metrics.v1.metrics_service_pb2 import ExportMetricsServiceResponse
        from opentelemetry.proto.collector.trace.v1 import trace_service_pb2_grpc
        from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ExportTraceServiceResponse
    except Exception as exc:  # pragma: no cover - import guard path
        raise RuntimeError(
            "OTLP gRPC dependencies are not available. Install grpcio and opentelemetry-proto."
        ) from exc

    class _TraceService(trace_service_pb2_grpc.TraceServiceServicer):
        def Export(self, request, context):  # noqa: N802
            payload: dict[str, Any] = MessageToDict(request, preserving_proto_field_name=False)
            ingest_callback(payload)
            return ExportTraceServiceResponse()

    class _LogsService(logs_service_pb2_grpc.LogsServiceServicer):
        def Export(self, request, context):  # noqa: N802
            payload: dict[str, Any] = MessageToDict(request, preserving_proto_field_name=False)
            ingest_callback(payload)
            return ExportLogsServiceResponse()

    class _MetricsService(metrics_service_pb2_grpc.MetricsServiceServicer):
        def Export(self, request, context):  # noqa: N802
            payload: dict[str, Any] = MessageToDict(request, preserving_proto_field_name=False)
            ingest_callback(payload)
            return ExportMetricsServiceResponse()

    server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
    trace_service_pb2_grpc.add_TraceServiceServicer_to_server(_TraceService(), server)
    logs_service_pb2_grpc.add_LogsServiceServicer_to_server(_LogsService(), server)
    metrics_service_pb2_grpc.add_MetricsServiceServicer_to_server(_MetricsService(), server)
    server.add_insecure_port(f"0.0.0.0:{port}")
    server.start()
    return server
