package com.njcn.msgpush.module.push.dal.redis;

import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @author caozehui
 * @data 2026-03-25
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RateLimitRedisDAO {
    private final RedisTemplate<String, String> redisTemplate;

    private final String RATE_LIMIT_KEY_PREFIX = "msgPush:rate_limit";

    private String buildKey(String channel, String appName, String receiver) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        return RATE_LIMIT_KEY_PREFIX + channel + ":" + appName + ":" + receiver + ":" + LocalDate.now().format(dtf);
    }

    public void set(String channel, String appName, String receiver) {
        String key = buildKey(channel, appName, receiver);

        long now = System.currentTimeMillis();
        long tomorrowZero = LocalDate.now().plusDays(1).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        long ttl = tomorrowZero - now;
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(key, "1", ttl, TimeUnit.MILLISECONDS);
        if (!absent) {
            Integer oldCount = this.get(channel, appName, receiver);
            redisTemplate.opsForValue().set(key, (oldCount + 1) + "", ttl, TimeUnit.MILLISECONDS);
        }
    }

    public Integer get(String channel, String appName, String receiver) {
        String key = buildKey(channel, appName, receiver);
        String countStr = redisTemplate.opsForValue().get(key);
        return ObjectUtil.isNull(countStr) ? 0 : Integer.parseInt(countStr);
    }
}
