using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Extensions.Hosting;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using StellaOps.Auth;

namespace StellaOps.Authority;

/// <summary>
/// Configures OpenTelemetry primitives for the Authority host.
/// </summary>
internal static class AuthorityTelemetryConfiguration
{
    public static void Configure(WebApplicationBuilder builder)
    {
        ArgumentNullException.ThrowIfNull(builder);

        builder.Services.AddSingleton<ActivitySource>(_ => new ActivitySource(AuthorityTelemetry.ActivitySourceName));
        builder.Services.AddSingleton<Meter>(_ => new Meter(AuthorityTelemetry.MeterName));

        var openTelemetry = builder.Services.AddOpenTelemetry();
        var serviceVersion = AuthorityTelemetry.ResolveServiceVersion(typeof(AuthorityTelemetryConfiguration).Assembly);

        openTelemetry.ConfigureResource(resource =>
        {
            resource.AddService(
                serviceName: AuthorityTelemetry.ServiceName,
                serviceNamespace: AuthorityTelemetry.ServiceNamespace,
                serviceVersion: serviceVersion,
                serviceInstanceId: Environment.MachineName);

            resource.AddAttributes(new[]
            {
                new KeyValuePair<string, object>("deployment.environment", builder.Environment.EnvironmentName)
            });
        });

        openTelemetry.WithTracing(tracing =>
        {
            tracing
                .AddSource(AuthorityTelemetry.ActivitySourceName)
                .AddAspNetCoreInstrumentation()
                .AddHttpClientInstrumentation();
        });

        openTelemetry.WithMetrics(metrics =>
        {
            metrics
                .AddMeter(AuthorityTelemetry.MeterName)
                .AddAspNetCoreInstrumentation()
                .AddRuntimeInstrumentation();
        });
    }
}
