package com.pig4cloud.pig.marketing.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;

/**
 * 推送频率工具类
 * 
 * @author WCL
 * @date 2025-09-04
 * @description 提供推送频率检查的公共方法
 */
@Slf4j
public class PushFrequencyUtil {

    /**
     * 检查推送频率
     * 
     * @param pushFrequency 推送频率字符串
     * @param ruleId 规则ID
     * @param clientId 客户端id
     * @param redisTemplate Redis模板
     * @return 是否应该推送
     */
    public static boolean checkPushFrequency(String pushFrequency, Long ruleId, String clientId, RedisTemplate<String, Object> redisTemplate) {
        if (pushFrequency == null || pushFrequency.trim().isEmpty()) {
            log.debug("规则{}的推送频率为空，默认推送", ruleId);
            return true;
        }
        
        try {
            BigDecimal frequency = new BigDecimal(pushFrequency).setScale(2, RoundingMode.HALF_UP);
            
            if (frequency.compareTo(BigDecimal.ONE) < 0) {
                // 小于1则按概率推送
                double random = Math.random();
                boolean shouldPush = random <= frequency.doubleValue();
                log.debug("规则{}推送频率{}小于1，{}%几率推送，结果：{}", ruleId, frequency, frequency.multiply(new BigDecimal(100)), shouldPush);
                return shouldPush;
            } else if (frequency.compareTo(BigDecimal.ONE) == 0) {
                // 等于1则每次都推送
                log.debug("规则{}推送频率为1，每次都推送", ruleId);
                return true;
            } else {
                // 大于1则向上取整转换为整数周期
                int cycle = frequency.setScale(0, RoundingMode.CEILING).intValue();
                log.debug("规则{}推送频率{}大于1，向上取整为周期{}", ruleId, frequency, cycle);
                
                // 使用Redis管理周期计数
                return checkPushCycleWithRedis(ruleId, clientId, cycle, redisTemplate);
            }
        } catch (NumberFormatException e) {
            log.warn("规则{}的推送频率格式错误：{}，默认推送", ruleId, pushFrequency);
            return true;
        }
    }
    
    /**
     * 使用Redis检查推送周期
     * 
     * @param ruleId 规则ID
     * @param clientId 客户端id
     * @param cycle 周期
     * @param redisTemplate Redis模板
     * @return 是否应该推送
     */
    private static boolean checkPushCycleWithRedis(Long ruleId, String clientId, int cycle, RedisTemplate<String, Object> redisTemplate) {
        if (cycle < 1) {
            return false;
        }
        
        if (ruleId == null || ruleId <= 0) {
            ruleId = 6L;
        }

        String countKey = String.format("mkt:push:count:%d:%s", ruleId, clientId);
        
        try {
            // 获取当前计数
            String countStr = (String) redisTemplate.opsForValue().get(countKey);
            Long currentCount = null;
            
            if (countStr != null) {
                try {
                    currentCount = Long.parseLong(countStr);
                } catch (NumberFormatException e) {
                    redisTemplate.delete(countKey);
                }
            }
            
            if (currentCount == null) {
                // 第一次访问，设置计数为1
                redisTemplate.opsForValue().set(countKey, "1", 24, TimeUnit.HOURS);
                return true;
            }
            
            if (currentCount == cycle) {
                // 达到周期，重置并推送
                redisTemplate.delete(countKey);
                return true;
            }
            
            // 未达到周期，计数+1
            redisTemplate.opsForValue().set(countKey, String.valueOf(currentCount + 1), 24, TimeUnit.HOURS);
            return false;
            
        } catch (Exception e) {
            log.error("Redis操作异常，规则ID：{}，客户端ID：{}", ruleId, clientId, e);
            return true;
        }
    }
}