package com.spot.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * MQ消息幂等过滤器，基于 Redis 防止消息重复消费
 * 消息ID写入 Redis 后自动10分钟过期
 *
 * @author jean
 * @date 2026-05-06
 */
@Slf4j
@Component
public class MessageIdFilter {

    /** Redis Key 前缀 */
    private static final String REDIS_KEY_PREFIX = "spot:message:id:";

    /** 消息ID TTL（分钟） */
    private static final long EXPIRE_MINUTES = 10;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 检查消息ID是否已处理过
     * Redis 异常时返回 false，允许继续处理，避免因 Redis 故障导致消息丢失
     *
     * @param messageId 消息ID
     * @return true-已处理，false-未处理
     */
    public boolean isProcessed(String messageId) {
        if (messageId == null || messageId.trim().isEmpty()) {
            return false;
        }
        try {
            return Boolean.TRUE.equals(stringRedisTemplate.hasKey(REDIS_KEY_PREFIX + messageId));
        } catch (Exception e) {
            log.error("检查消息ID是否已处理时发生错误 - MessageId: {}", messageId, e);
            return false;
        }
    }

    /**
     * 标记消息ID为已处理，10分钟后自动过期
     *
     * @param messageId 消息ID
     */
    public void markAsProcessed(String messageId) {
        if (messageId == null || messageId.trim().isEmpty()) {
            return;
        }
        try {
            stringRedisTemplate.opsForValue().set(
                    REDIS_KEY_PREFIX + messageId,
                    String.valueOf(TimeUtils.currentUtcTimestamp()),
                    EXPIRE_MINUTES, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("标记消息ID为已处理时发生错误 - MessageId: {}", messageId, e);
        }
    }

    /**
     * 移除消息ID标记，用于业务处理失败时回滚幂等标记
     *
     * @param messageId 消息ID
     */
    public void removeProcessed(String messageId) {
        if (messageId == null || messageId.trim().isEmpty()) {
            return;
        }
        try {
            stringRedisTemplate.delete(REDIS_KEY_PREFIX + messageId);
        } catch (Exception e) {
            log.error("移除消息ID标记时发生错误 - MessageId: {}", messageId, e);
        }
    }
}
