package com.sqx.common.utils;

import cn.hutool.core.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;


/**
 * 数据出现次数
 */
@Component
public class DataLimitUtil {

    private static final String ACCESS_COUNT_KEY_PREFIX = "sys:data:";

    private static RedisUtils redisUtils;

    private static final int DEFAULT_ACCESS_COUNT = 5;
    private static final String DATE_TIME_FORMAT = "month";


    @Autowired
    public void setRedisUtils(RedisUtils redisUtils) {
        DataLimitUtil.redisUtils = redisUtils;
    }

    /**
     * 默认 当月5次
     *
     * @param key 名称  sys:data:名称
     * @return
     */
    public static boolean isAccessAllowed(String key) {
        String redisKey = generateRedisKey(key);
        Object countObj = redisUtils.get(redisKey);
        if (countObj == null) {
            // 根据不同时间周期设置过期时间并初始化访问次数为1
            long expireAt = calculateExpireAt(DATE_TIME_FORMAT);
            redisUtils.set(redisKey, 1, expireAt);
            return true;
        }
        if ((int) countObj < DEFAULT_ACCESS_COUNT) {
            // 访问次数未达上限，次数加1
            redisUtils.incr(redisKey);
            return true;
        }
        return false;
    }


    /**
     * 默认月 month/月/自然月
     *
     * @param key   名称  sys:data:名称
     * @param count 次数限制
     * @return
     */
    public static boolean isAccessAllowed(String key, Integer count) {
        String redisKey = generateRedisKey(key);
        Object countObj = redisUtils.get(redisKey);
        if (countObj == null) {
            // 根据不同时间周期设置过期时间并初始化访问次数为1
            long expireAt = calculateExpireAt(DATE_TIME_FORMAT);
            redisUtils.set(redisKey, 1, expireAt);
            return true;
        }
        if ((int) countObj < count) {
            // 访问次数未达上限，次数加1
            redisUtils.incr(redisKey);
            return true;
        }
        return false;
    }

    /**
     * 默认 5次
     *
     * @param key        名称  sys:data:名称
     * @param timeFormat day/天/自然天 week/周/本周日 month/月/自然月 year/年/自然年
     * @return
     */
    public static boolean isAccessAllowed(String key, String timeFormat) {
        String redisKey = generateRedisKey(key);
        Object countObj = redisUtils.get(redisKey);
        if (countObj == null) {
            // 根据不同时间周期设置过期时间并初始化访问次数为1
            long expireAt = calculateExpireAt(timeFormat);
            redisUtils.set(redisKey, 1, expireAt);
            return true;
        }
        if ((int) countObj < DEFAULT_ACCESS_COUNT) {
            // 访问次数未达上限，次数加1
            redisUtils.incr(redisKey);
            return true;
        }
        return false;
    }

    public static boolean isAllowed(String key, int seconds) {
        String redisKey = generateRedisKey(key);
        if (!redisUtils.hasKey(key)) {
            redisUtils.set(redisKey, 1, seconds);
            return true;
        }
        return false;
    }

    /**
     * @param key        名称  sys:data:名称
     * @param count      次数限制
     * @param timeFormat day/天/自然天 week/周/本周日 month/月/自然月 year/年/自然年
     * @return
     */
    public static boolean isAccessAllowed(String key, Integer count, String timeFormat) {
        String redisKey = generateRedisKey(key);
        Object countObj = redisUtils.get(redisKey);
        if (countObj == null) {
            // 根据不同时间周期设置过期时间并初始化访问次数为1
            long expireAt = calculateExpireAt(timeFormat);
            redisUtils.set(redisKey, 1, expireAt);
            return true;
        }
        if (Integer.parseInt(countObj.toString()) < count) {
            // 访问次数未达上限，次数加1
            redisUtils.incr(redisKey);
            return true;
        }
        return false;
    }


    private static String generateRedisKey(String key) {
        return ACCESS_COUNT_KEY_PREFIX + key;
    }

    private static long calculateExpireAt(String timePeriod) {
        Date now = DateUtil.beginOfDay(DateUtil.date());
        Date expireDate = null;
        if ("day".equals(timePeriod)) {
            expireDate = DateUtil.endOfDay(now);
        } else if ("week".equals(timePeriod)) {
            expireDate = DateUtil.endOfWeek(now);
        } else if ("month".equals(timePeriod)) {
            expireDate = DateUtil.endOfMonth(now);
        } else if ("year".equals(timePeriod)) {
            expireDate = DateUtil.endOfYear(now);
        }
        long endTimeStamp = DateUtil.endOfDay(expireDate).getTime() / 1000L;
        long currentTimeStamp = DateUtil.currentSeconds();
        return endTimeStamp - currentTimeStamp;
    }
}