using System.Diagnostics;
using Nexus.Api.Observability;
using Nexus.Api.Http;
using Npgsql;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace Nexus.Api.Extensions;

public static class PlatformServiceCollectionExtensions
{
    /// <summary>
    /// Registers the canonical OpenAPI document and privacy-safe telemetry.
    /// OTLP export is opt-in; without an endpoint Nexus keeps only in-process
    /// instrumentation and does not add a production telemetry service.
    /// </summary>
    public static IServiceCollection AddNexusPlatform(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        services.AddOpenApi("v1", options =>
            options.AddSchemaTransformer<NexusProblemDetailsSchemaTransformer>());
        services.AddProblemDetails(options =>
        {
            options.CustomizeProblemDetails = context =>
                NexusProblemDetailsDefaults.Apply(
                    context.ProblemDetails,
                    context.HttpContext);
        });

        var telemetry = services.AddOpenTelemetry()
            .ConfigureResource(resource => resource.AddService(
                serviceName: "nexus-api",
                serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString()))
            .WithMetrics(metrics => metrics
                .AddAspNetCoreInstrumentation()
                .AddHttpClientInstrumentation()
                .AddRuntimeInstrumentation()
                .AddMeter(NexusTelemetry.SourceName))
            .WithTracing(tracing => tracing
                .AddAspNetCoreInstrumentation(options =>
                {
                    // Exception messages and stack traces may contain prompts,
                    // paths or other operator content.
                    options.RecordException = false;
                    options.Filter = context =>
                        !context.Request.Path.StartsWithSegments("/health");
                })
                .AddHttpClientInstrumentation(options =>
                {
                    options.RecordException = false;
                })
                .AddNpgsql()
                .AddSource(NexusTelemetry.SourceName)
                .AddProcessor(new NexusTelemetryRedactionProcessor()));

        var endpointValue = configuration["OpenTelemetry:OtlpEndpoint"]
            ?? Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT");
        if (Uri.TryCreate(endpointValue, UriKind.Absolute, out var endpoint))
        {
            telemetry.UseOtlpExporter(OtlpExportProtocol.Grpc, endpoint);
        }

        return services;
    }
}
