using System.Threading.RateLimiting;

namespace Atomx.Admin.Extensions
{
    public static class RateLimiterExtension
    {
        /// <summary>
        /// 添加速率限制
        /// </summary>
        /// <param name="services"></param>
        /// <param name="Configuration"></param>
        /// <param name="environment"></param>
        /// <exception cref="Exception"></exception>
        public static void AddRateLimiter(this IServiceCollection services, IConfiguration Configuration, IWebHostEnvironment environment)
        {
            // 速率限制
            services.AddRateLimiter(limiterOptions =>
            {
                limiterOptions.RejectionStatusCode = StatusCodes.Status429TooManyRequests;

                // 全局限制
                limiterOptions.AddPolicy("global", context =>
                    RateLimitPartition.GetFixedWindowLimiter(
                        partitionKey: context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
                        factory: _ => new FixedWindowRateLimiterOptions
                        {
                            PermitLimit = 100,
                            Window = TimeSpan.FromMinutes(1),
                            QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                            QueueLimit = 2
                        }));

                // 登录限制
                limiterOptions.AddPolicy("login", context =>
                    RateLimitPartition.GetFixedWindowLimiter(
                        partitionKey: $"{context.Connection.RemoteIpAddress}_{context.Request.Path}",
                        factory: _ => new FixedWindowRateLimiterOptions
                        {
                            PermitLimit = 5,
                            Window = TimeSpan.FromMinutes(15),
                            QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                            QueueLimit = 0
                        }));
            });


            //// HTTP客户端工厂
            //services.AddHttpClient("ApiClient")
            //    .AddTransientHttpErrorPolicy(policy =>
            //        policy.WaitAndRetryAsync(3, retryAttempt =>
            //            TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))))
            //    .AddTransientHttpErrorPolicy(policy =>
            //        policy.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
        }
    }
}
