using LittleShop.Client.Configuration;
using LittleShop.Client.Http;
using LittleShop.Client.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace LittleShop.Client.Extensions;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddLittleShopClient(
        this IServiceCollection services,
        Action<LittleShopClientOptions>? configureOptions = null)
    {
        // Configure options
        if (configureOptions != null)
        {
            services.Configure(configureOptions);
        }
        else
        {
            services.Configure<LittleShopClientOptions>(options => { });
        }
        
        // Register HTTP handlers
        services.AddTransient<RetryPolicyHandler>();
        services.AddTransient<ErrorHandlingMiddleware>();
        
        // Register main HTTP client
        services.AddHttpClient<IAuthenticationService, AuthenticationService>((serviceProvider, client) =>
        {
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        })
        .AddHttpMessageHandler<ErrorHandlingMiddleware>()
        .AddHttpMessageHandler(serviceProvider =>
        {
            var logger = serviceProvider.GetRequiredService<ILogger<RetryPolicyHandler>>();
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            return new RetryPolicyHandler(logger, options.MaxRetryAttempts);
        });
        
        services.AddHttpClient<ICatalogService, CatalogService>((serviceProvider, client) =>
        {
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        })
        .AddHttpMessageHandler<ErrorHandlingMiddleware>()
        .AddHttpMessageHandler(serviceProvider =>
        {
            var logger = serviceProvider.GetRequiredService<ILogger<RetryPolicyHandler>>();
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            return new RetryPolicyHandler(logger, options.MaxRetryAttempts);
        });
        
        services.AddHttpClient<IOrderService, OrderService>((serviceProvider, client) =>
        {
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        })
        .AddHttpMessageHandler<ErrorHandlingMiddleware>()
        .AddHttpMessageHandler(serviceProvider =>
        {
            var logger = serviceProvider.GetRequiredService<ILogger<RetryPolicyHandler>>();
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            return new RetryPolicyHandler(logger, options.MaxRetryAttempts);
        });
        
        services.AddHttpClient<ICustomerService, CustomerService>((serviceProvider, client) =>
        {
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        })
        .AddHttpMessageHandler<ErrorHandlingMiddleware>()
        .AddHttpMessageHandler(serviceProvider =>
        {
            var logger = serviceProvider.GetRequiredService<ILogger<RetryPolicyHandler>>();
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            return new RetryPolicyHandler(logger, options.MaxRetryAttempts);
        });

        services.AddHttpClient<IMessageService, MessageService>((serviceProvider, client) =>
        {
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            client.BaseAddress = new Uri(options.BaseUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        })
        .AddHttpMessageHandler<ErrorHandlingMiddleware>()
        .AddHttpMessageHandler(serviceProvider =>
        {
            var logger = serviceProvider.GetRequiredService<ILogger<RetryPolicyHandler>>();
            var options = serviceProvider.GetRequiredService<IOptions<LittleShopClientOptions>>().Value;
            return new RetryPolicyHandler(logger, options.MaxRetryAttempts);
        });
        
        // Register the main client
        services.AddScoped<ILittleShopClient, LittleShopClient>();
        
        return services;
    }
    
    public static IServiceCollection AddLittleShopClient(
        this IServiceCollection services,
        string baseUrl)
    {
        return services.AddLittleShopClient(options =>
        {
            options.BaseUrl = baseUrl;
        });
    }
}