using MiningService.API.ExternalServices;
using Polly;
using Polly.Extensions.Http;

namespace MiningService.API.Extensions;

/// <summary>
/// EN: Extension methods for registering external service clients.
/// VI: Extension methods để đăng ký các external service clients.
/// </summary>
public static class ExternalServicesExtensions
{
    public static IServiceCollection AddExternalServices(this IServiceCollection services, IConfiguration configuration)
    {
        // IAM Service Client
        services.AddHttpClient<IIamServiceClient, IamServiceClient>(client =>
        {
            client.BaseAddress = new Uri(configuration["ExternalServices:IamService:BaseUrl"] ?? "http://iam-service-net:8080");
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            client.Timeout = TimeSpan.FromSeconds(30);
        })
        .AddPolicyHandler(GetRetryPolicy())
        .AddPolicyHandler(GetCircuitBreakerPolicy());

        // Wallet Service Client
        services.AddHttpClient<IWalletServiceClient, WalletServiceClient>(client =>
        {
            client.BaseAddress = new Uri(configuration["ExternalServices:WalletService:BaseUrl"] ?? "http://wallet-service-net:8080");
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            client.Timeout = TimeSpan.FromSeconds(30);
        })
        .AddPolicyHandler(GetRetryPolicy())
        .AddPolicyHandler(GetCircuitBreakerPolicy());

        // Social Service Client
        services.AddHttpClient<ISocialServiceClient, SocialServiceClient>(client =>
        {
            client.BaseAddress = new Uri(configuration["ExternalServices:SocialService:BaseUrl"] ?? "http://social-service-net:8080");
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            client.Timeout = TimeSpan.FromSeconds(30);
        })
        .AddPolicyHandler(GetRetryPolicy())
        .AddPolicyHandler(GetCircuitBreakerPolicy());

        return services;
    }

    private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
    }

    private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
    }
}
