using System;
using System.Net;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using StellaOps.Feedser.Source.Common.Http;
using StellaOps.Feedser.Source.Ics.Cisa.Configuration;
using StellaOps.Feedser.Source.Ics.Cisa.Internal;

namespace StellaOps.Feedser.Source.Ics.Cisa;

public static class IcsCisaServiceCollectionExtensions
{
    public static IServiceCollection AddIcsCisaConnector(this IServiceCollection services, Action<IcsCisaOptions> configure)
    {
        ArgumentNullException.ThrowIfNull(services);
        ArgumentNullException.ThrowIfNull(configure);

        services.AddOptions<IcsCisaOptions>()
            .Configure(configure)
            .PostConfigure(static opts => opts.Validate());

        services.AddSourceHttpClient(IcsCisaOptions.HttpClientName, (sp, clientOptions) =>
        {
            var options = sp.GetRequiredService<IOptions<IcsCisaOptions>>().Value;
            clientOptions.BaseAddress = new Uri(options.TopicsEndpoint.GetLeftPart(UriPartial.Authority));
            clientOptions.Timeout = TimeSpan.FromSeconds(45);
            clientOptions.UserAgent = "StellaOps.Feedser.IcsCisa/1.0";
            clientOptions.AllowedHosts.Clear();
            clientOptions.AllowedHosts.Add(options.TopicsEndpoint.Host);
            clientOptions.AllowedHosts.Add(options.DetailBaseUri.Host);
            foreach (var host in options.AdditionalHosts)
            {
                clientOptions.AllowedHosts.Add(host);
            }
            clientOptions.DefaultRequestHeaders["Accept"] = "application/rss+xml";
            clientOptions.RequestVersion = options.RequestVersion;
            clientOptions.VersionPolicy = options.RequestVersionPolicy;
            clientOptions.MaxAttempts = options.MaxAttempts;
            clientOptions.BaseDelay = options.BaseDelay;
            clientOptions.EnableMultipleHttp2Connections = false;

            clientOptions.ConfigureHandler = handler =>
            {
                handler.AutomaticDecompression = DecompressionMethods.All;
            };

            if (options.ProxyUri is not null)
            {
                clientOptions.ProxyAddress = options.ProxyUri;
                clientOptions.ProxyBypassOnLocal = false;
            }
        });

        services.AddSingleton<IcsCisaDiagnostics>();
        services.AddSingleton<IcsCisaFeedParser>();
        services.AddTransient<IcsCisaConnector>();

        return services;
    }
}
