package com.spot.utils;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 订单处理过滤器 - 防止重复处理相同订单ID+状态的组合
 * 使用 Caffeine 缓存实现自动过期，过期时间：5分钟
 * 支持"正在处理"标记，避免并发重复处理
 *
 * @author jean
 * @date 2026-05-07
 */
@Component
@Slf4j
public class OrderProcessedFilter {

    /**
     * 已处理订单缓存 Key: orderId_status, Value: 处理时间
     * 写入后 5 分钟过期
     */
    private static final Cache<String, LocalDateTime> PROCESSED_ORDERS = Caffeine.newBuilder()
            .expireAfterWrite(Duration.ofMinutes(5))
            .build();

    /**
     * 正在处理的订单缓存 Key: orderId_status, Value: 开始处理时间
     * 写入后 10 分钟过期，防止异常情况导致标记永久存在
     */
    private static final Cache<String, LocalDateTime> PROCESSING_ORDERS = Caffeine.newBuilder()
            .expireAfterWrite(Duration.ofMinutes(10))
            .build();

    /**
     * 检查订单是否已经处理过
     *
     * @param orderId 订单ID
     * @param status  订单状态
     * @return true-已处理过，false-未处理过
     */
    public static boolean isProcessed(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            return false;
        }
        return PROCESSED_ORDERS.getIfPresent(buildKey(orderId, status)) != null;
    }

    /**
     * 检查订单是否正在处理中
     *
     * @param orderId 订单ID
     * @param status  订单状态
     * @return true-正在处理，false-未在处理
     */
    public static boolean isProcessing(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            return false;
        }
        return PROCESSING_ORDERS.getIfPresent(buildKey(orderId, status)) != null;
    }

    /**
     * 标记订单为正在处理（处理前调用）
     *
     * @param orderId 订单ID
     * @param status  订单状态
     * @return true-标记成功（之前未在处理），false-标记失败（已经在处理中）
     */
    public static boolean markAsProcessing(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            log.warn("订单ID或状态为空，无法标记为正在处理");
            return false;
        }
        String key = buildKey(orderId, status);
        if (PROCESSING_ORDERS.getIfPresent(key) != null) {
            log.debug("订单正在处理中，跳过重复处理 - OrderId: {}, Status: {}", orderId, status);
            return false;
        }
        if (PROCESSED_ORDERS.getIfPresent(key) != null) {
            log.debug("订单已处理过，跳过重复处理 - OrderId: {}, Status: {}", orderId, status);
            return false;
        }
        PROCESSING_ORDERS.put(key, LocalDateTime.now());
        log.debug("订单已标记为正在处理 - OrderId: {}, Status: {}", orderId, status);
        return true;
    }

    /**
     * 标记订单为已处理（处理后调用），同时清除"正在处理"标记
     *
     * @param orderId 订单ID
     * @param status  订单状态
     */
    public static void markAsProcessed(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            log.warn("订单ID或状态为空，无法标记为已处理");
            return;
        }
        String key = buildKey(orderId, status);
        PROCESSED_ORDERS.put(key, LocalDateTime.now());
        PROCESSING_ORDERS.invalidate(key);
        log.debug("订单已标记为已处理，并清除正在处理标记 - OrderId: {}, Status: {}", orderId, status);
    }

    /**
     * 清除正在处理标记（处理失败时调用，允许重试）
     *
     * @param orderId 订单ID
     * @param status  订单状态
     */
    public static void clearProcessing(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            return;
        }
        PROCESSING_ORDERS.invalidate(buildKey(orderId, status));
        log.debug("已清除订单的正在处理标记 - OrderId: {}, Status: {}", orderId, status);
    }

    /** 构建缓存 Key */
    private static String buildKey(Long orderId, Integer status) {
        return orderId + "_" + status;
    }
}
