package cn.com.ctop.common.module.utils;

import com.google.common.collect.ImmutableMap;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@RequiredArgsConstructor
public class RateLimitUtil {
    @Autowired
    public RedissonClient redissonClient;
    private static final Map<String, Boolean> initMap = new ConcurrentHashMap<>();
    private static final Map<String, Integer> pathQpsMap = new ImmutableMap.Builder<String, Integer>()
            .put("/open_api/v3.0/report/custom/get/", 21)
            .put("/open_api/2/file/video/get/", 10)
            .put("/open_api/v3.0/promotion/list/", 27)
            .put("/open_api/v3.0/project/list/", 10)
            .put("/open_api/2/customer_center/advertiser/list/", 50)
            .put("/open_api/v3.0/tools/micro_app/list/", 10)
            .put("/open_api/v3.0/tools/asset_link/list/", 10)
            .put("/open_api/v3.0/tools/wechat_applet/list/", 10)
            .put("/open_api/2/advertiser/fund/daily_stat/", 50)
            .put("/open_api/2/advertiser/avatar/get/", 10)
            .put("/open_api/2/agent/advertiser_info/query/", 10)
            .put("/open_api/2/tools/site/get/", 10)
            .put("/open_api/2/report/advertiser/get/", 27)
            .put("/open_api/v3.0/project/status/update/", 30)
            .build();


    public synchronized boolean acquire(String devAppId, String url) {
        URI uri = URI.create(url);
        String path = uri.getPath();
        String limitKey = path.replaceAll("/$", "").replace("/", ":");
        String key = "rate:limit" + limitKey + (Check.isNull(devAppId) ? "" : ":" + devAppId);
        if (!initMap.containsKey(key)) {
            Integer qps = pathQpsMap.getOrDefault(path, 10);
            RRateLimiter limiter = redissonClient.getRateLimiter(key);
            limiter.setRate(
                    RateType.OVERALL,
                    qps / 2,
                    500,
                    RateIntervalUnit.MILLISECONDS
            );
            initMap.put(key, true);
        }
        return redissonClient.getRateLimiter(key).tryAcquire(1, 1, TimeUnit.SECONDS);

    }
}
