using System.Net;
using Microsoft.Extensions.Logging;
using Polly;
using Polly.Extensions.Http;

namespace LittleShop.Client.Http;

public class RetryPolicyHandler : DelegatingHandler
{
    private readonly ILogger<RetryPolicyHandler> _logger;
    private readonly IAsyncPolicy<HttpResponseMessage> _retryPolicy;
    
    public RetryPolicyHandler(ILogger<RetryPolicyHandler> logger, int maxRetryAttempts = 3)
    {
        _logger = logger;
        
        _retryPolicy = HttpPolicyExtensions
            .HandleTransientHttpError()
            .OrResult(msg => !msg.IsSuccessStatusCode && msg.StatusCode != HttpStatusCode.Unauthorized)
            .WaitAndRetryAsync(
                maxRetryAttempts,
                retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                onRetry: (outcome, timespan, retryCount, context) =>
                {
                    var reason = outcome.Result?.StatusCode.ToString() ?? outcome.Exception?.Message;
                    _logger.LogWarning(
                        "Retry {RetryCount} after {TimeSpan}ms due to: {Reason}",
                        retryCount, timespan.TotalMilliseconds, reason);
                });
    }
    
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, 
        CancellationToken cancellationToken)
    {
        return await _retryPolicy.ExecuteAsync(async () =>
            await base.SendAsync(request, cancellationToken));
    }
}