from __future__ import annotations

import os

from opentelemetry.sdk.trace.export import SpanExportResult

import app.utils.structured_otlp as structured_otlp


class _RecordingExporter:
    def __init__(self, *args: object, **kwargs: object) -> None:
        self.exported: list[int] = []
        self.shutdown_calls = 0

    def export(self, spans: object) -> SpanExportResult:
        self.exported.append(len(list(spans)))
        return SpanExportResult.SUCCESS

    def shutdown(self) -> None:
        self.shutdown_calls += 1

    def force_flush(self, timeout_millis: int = 30_000) -> bool:
        return True


def _reset_provider_without_shutdown() -> None:
    with structured_otlp._TRACER_LOCK:
        structured_otlp._TRACER = None
        structured_otlp._TRACER_PROVIDER = None
        structured_otlp._TRACER_ENDPOINT = ""


def test_span_export_is_batched_not_synchronous(monkeypatch) -> None:
    old_endpoint = os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
    os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = "http://localhost:4318/v1/traces"
    exporter = _RecordingExporter()
    monkeypatch.setattr(
        structured_otlp,
        "OTLPSpanExporter",
        lambda *args, **kwargs: exporter,
    )
    _reset_provider_without_shutdown()
    try:
        structured_otlp.publish_structured_span(
            {
                "session_id": "0123456789abcdef0123456789abcdef",
                "tipo_evento": "audio_in",
                "dat_hora_inicio": "2026-07-24T12:00:00.000000Z",
                "dat_hora_fim": "2026-07-24T12:00:00.010000Z",
            }
        )

        assert exporter.exported == []
        assert structured_otlp.force_flush_structured_otlp(timeout_millis=5_000)
        assert sum(exporter.exported) >= 1
    finally:
        structured_otlp.shutdown_structured_otlp()
        if old_endpoint is None:
            os.environ.pop("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", None)
        else:
            os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = old_endpoint


def test_shutdown_flushes_provider_once(monkeypatch) -> None:
    old_endpoint = os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
    os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = "http://localhost:4318/v1/traces"
    exporter = _RecordingExporter()
    monkeypatch.setattr(
        structured_otlp,
        "OTLPSpanExporter",
        lambda *args, **kwargs: exporter,
    )
    _reset_provider_without_shutdown()
    try:
        assert structured_otlp._tracer() is not None
        structured_otlp.shutdown_structured_otlp()
        structured_otlp.shutdown_structured_otlp()
        assert exporter.shutdown_calls == 1
        assert structured_otlp._TRACER_PROVIDER is None
    finally:
        structured_otlp.shutdown_structured_otlp()
        if old_endpoint is None:
            os.environ.pop("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", None)
        else:
            os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = old_endpoint
