use crate::observability::config::TraceConfig;
use crate::observability::filter::SharedOrderedFilter;
use crate::observability::remote::{append_otlp_path, resource};
use anyhow::{bail, Context as AnyhowContext, Result};
use opentelemetry::trace::TracerProvider;
use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig};
use opentelemetry_sdk::trace::SdkTracerProvider;
use tracing_subscriber::{Layer, Registry};

/// Builds the OpenTelemetry tracing layer and provider.
pub fn build_trace_layer(
    config: &TraceConfig,
    filter: SharedOrderedFilter,
) -> Result<(Box<dyn Layer<Registry> + Send + Sync>, SdkTracerProvider)> {
    if config.exporter != "otlp" {
        bail!("unsupported trace exporter `{}`", config.exporter);
    }

    let endpoint = append_otlp_path(&config.endpoint, "/v1/traces");
    let exporter = SpanExporter::builder()
        .with_http()
        .with_protocol(Protocol::HttpBinary)
        .with_endpoint(endpoint)
        .build()
        .context("failed to create OpenTelemetry trace exporter")?;

    let provider = SdkTracerProvider::builder()
        .with_batch_exporter(exporter)
        .with_resource(resource(config))
        .build();

    let tracer = provider.tracer("pi_logger");
    let layer = tracing_opentelemetry::layer()
        .with_tracer(tracer)
        .with_filter(filter)
        .boxed();

    Ok((layer, provider))
}