package cn.novalon.manage.gateway.config;

import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * 限流配置类
 * 
 * 文件定义：配置API限流策略，使用Resilience4j实现
 * 涉及业务：API访问频率控制，防止滥用和DDoS攻击
 * 算法：使用Resilience4j的RateLimiter实现令牌桶算法
 * 
 * 支持多种限流策略：
 * 1. 全局限流：对所有API请求进行统一限流
 * 2. IP限流：基于客户端IP地址进行限流
 * 3. 用户限流：基于用户ID进行限流
 * 4. API路径限流：基于API路径进行差异化限流
 * 
 * @author 张翔
 * @date 2026-03-13
 */
@Configuration
public class RateLimitConfig {

    private static final Logger logger = LoggerFactory.getLogger(RateLimitConfig.class);

    @Value("${rate.limit.global.limit-for-period:1000}")
    private int globalLimitForPeriod;

    @Value("${rate.limit.global.limit-refresh-period:1s}")
    private Duration globalLimitRefreshPeriod;

    @Value("${rate.limit.global.timeout-duration:0}")
    private Duration globalTimeoutDuration;

    @Value("${rate.limit.ip.limit-for-period:100}")
    private int ipLimitForPeriod;

    @Value("${rate.limit.ip.limit-refresh-period:1s}")
    private Duration ipLimitRefreshPeriod;

    @Value("${rate.limit.ip.timeout-duration:0}")
    private Duration ipTimeoutDuration;

    @Value("${rate.limit.user.limit-for-period:200}")
    private int userLimitForPeriod;

    @Value("${rate.limit.user.limit-refresh-period:1s}")
    private Duration userLimitRefreshPeriod;

    @Value("${rate.limit.user.timeout-duration:0}")
    private Duration userTimeoutDuration;

    @Value("${rate.limit.enabled:true}")
    private boolean rateLimitEnabled;

    @Bean
    public RateLimiterRegistry rateLimiterRegistry() {
        Map<String, RateLimiterConfig> configs = new HashMap<>();
        
        configs.put("globalRateLimiter", createRateLimiterConfig(
                globalLimitForPeriod, globalLimitRefreshPeriod, globalTimeoutDuration));
        
        configs.put("ipRateLimiter", createRateLimiterConfig(
                ipLimitForPeriod, ipLimitRefreshPeriod, ipTimeoutDuration));
        
        configs.put("userRateLimiter", createRateLimiterConfig(
                userLimitForPeriod, userLimitRefreshPeriod, userTimeoutDuration));

        RateLimiterRegistry registry = RateLimiterRegistry.of(configs);
        
        logger.info("Rate limiter registry initialized with {} configurations", configs.size());
        logger.info("Global limit: {}/{}", globalLimitForPeriod, globalLimitRefreshPeriod);
        logger.info("IP limit: {}/{}", ipLimitForPeriod, ipLimitRefreshPeriod);
        logger.info("User limit: {}/{}", userLimitForPeriod, userLimitRefreshPeriod);
        
        return registry;
    }

    @Bean
    public RateLimiter globalRateLimiter(RateLimiterRegistry registry) {
        return registry.rateLimiter("globalRateLimiter");
    }

    @Bean
    public RateLimiter ipRateLimiter(RateLimiterRegistry registry) {
        return registry.rateLimiter("ipRateLimiter");
    }

    @Bean
    public RateLimiter userRateLimiter(RateLimiterRegistry registry) {
        return registry.rateLimiter("userRateLimiter");
    }

    private RateLimiterConfig createRateLimiterConfig(
            int limitForPeriod, 
            Duration limitRefreshPeriod, 
            Duration timeoutDuration) {
        return RateLimiterConfig.custom()
                .limitForPeriod(limitForPeriod)
                .limitRefreshPeriod(limitRefreshPeriod)
                .timeoutDuration(timeoutDuration)
                .build();
    }

    public boolean isRateLimitEnabled() {
        return rateLimitEnabled;
    }
}