package com.friday.custody.aop;

import java.util.concurrent.ConcurrentHashMap;

import com.friday.custody.enums.RetCodeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.utils.IPWhiteListUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class LimitByMap {
    //全局MAP key为userId+URI  value为CountParam 统计对象 记录时间和次数
    public static ConcurrentHashMap<String, CountParam> cacheMap = new ConcurrentHashMap<>();

    @Value("${ipWhilte}")
    private String ipWhiteList;

    /**
     * @param key       自定义key userId+URI
     * @param num       自定义限制请求次数 超出次数后限制访问
     * @param limitTime 自定义限制时间，限制时间内限制访问次数
     */
    public void limitRequest(String key, int num, Long limitTime) {//160.22.11.254
        String ip = key.split("-")[1];
        //判断ip是否在白名单内，没有则限制次数
        Boolean aBoolean = IPWhiteListUtil.checkLoginIP(ip,ipWhiteList);
        if (!aBoolean) {
            long currentTimeMillls = System.currentTimeMillis();
            //1 通过key获取到countPatam对象
            CountParam countParam = cacheMap.get(key);
            //2 判断对象是否为空，如果为空则代表第一次访问 如果不为空则代表之前请求过
            if (countParam != null) {
                //3 获取时间，用当前时间减去最后一次访问时间，如果规定时间则清零访问次数，小于则累加计数
                Long time = currentTimeMillls - countParam.getTime();
                int currentCount = countParam.getCount();
                log.info("the key is {}, the limitTime is {},the currentTimeMillls is {} ,the time gap is {} ,the currentCount is {}", key, limitTime, currentTimeMillls, time, currentCount);
                if (time < limitTime) {
                    //4 如果累计次数大于20，证明用户在限制时间内访问过多
                    if (currentCount >= num) {
                        log.warn("访问超出限制次数,IP{}",ip);
                        throw new RRException(RetCodeEnum.OPERATION_ERROR.getCode(), "访问超出限制次数,ip:"+ip);
                    } else {
                        countParam.setCount(++currentCount);
                    }
                } else {
                    countParam.setCount(1);
                    countParam.setTime(currentTimeMillls);
                }
                log.info("Count： {}", countParam.getCount());
            } else {
                countParam = new CountParam();
                countParam.setCount(1);
                countParam.setTime(currentTimeMillls);
            }
            cacheMap.put(key, countParam);
        }
    }

}