"""Module OpenTelemetry pour l'observabilité des services CEZAM."""

from __future__ import annotations

from opentelemetry import trace, metrics
from opentelemetry.trace import Tracer
from opentelemetry.metrics import Meter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.propagate import inject, extract
from opentelemetry import context as otel_context


def setup_otel(
    service_name: str,
    otel_endpoint: str = "localhost:4317",
) -> tuple[Tracer, Meter]:
    """Configure OpenTelemetry pour un service.

    Args:
        service_name: Nom du service (ex: "doc_classifier").
        otel_endpoint: Endpoint du collector OTLP (host:port).

    Returns:
        Tuple (tracer, meter) configurés.
    """
    resource = Resource.create({SERVICE_NAME: service_name})

    tracer_provider = TracerProvider(resource=resource)
    span_exporter = OTLPSpanExporter(endpoint=otel_endpoint, insecure=True)
    tracer_provider.add_span_processor(BatchSpanProcessor(span_exporter))
    trace.set_tracer_provider(tracer_provider)

    metric_reader = PeriodicExportingMetricReader(
        OTLPMetricExporter(endpoint=otel_endpoint, insecure=True),
        export_interval_millis=60000,
    )
    meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
    metrics.set_meter_provider(meter_provider)

    tracer = trace.get_tracer(service_name)
    meter = metrics.get_meter(service_name)

    return tracer, meter


def inject_trace_context(headers: dict) -> dict:
    """Injecte le contexte de trace dans les headers.

    Args:
        headers: Dictionnaire de headers à enrichir.

    Returns:
        Le dictionnaire headers avec le contexte de trace injecté.
    """
    inject(headers)
    return headers


def extract_trace_context(headers: dict) -> None:
    """Extrait et active le contexte de trace depuis les headers.

    Args:
        headers: Dictionnaire de headers contenant le contexte de trace.
    """
    ctx = extract(headers)
    otel_context.attach(ctx)
