package com.erp.order.service.impl;

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

import java.time.Duration;

/**
 * 订单服务幂等性工具
 * 使用Redis实现接口幂等性
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderIdempotencyService {

    private final RedisTemplate<String, Object> redisTemplate;

    /** 幂等键前缀 */
    private static final String IDEMPOTENT_KEY_PREFIX = "order:idempotent:";

    /** 默认过期时间 24小时 */
    private static final Duration DEFAULT_TTL = Duration.ofHours(24);

    /**
     * 检查请求是否已处理（幂等性检查）
     *
     * @param key 幂等键（如平台订单号）
     * @return true=已处理过（直接返回），false=新请求
     */
    public boolean isDuplicate(String key) {
        String redisKey = IDEMPOTENT_KEY_PREFIX + key;
        Boolean exists = redisTemplate.hasKey(redisKey);
        return Boolean.TRUE.equals(exists);
    }

    /**
     * 标记请求为已处理
     *
     * @param key  幂等键
     * @param value 存储的结果（如订单ID）
     */
    public void markProcessed(String key, Object value) {
        String redisKey = IDEMPOTENT_KEY_PREFIX + key;
        redisTemplate.opsForValue().set(redisKey, value, DEFAULT_TTL);
    }

    /**
     * 尝试获取已处理的结果
     *
     * @param key 幂等键
     * @return 已处理的结果，或null
     */
    public Object getProcessedResult(String key) {
        String redisKey = IDEMPOTENT_KEY_PREFIX + key;
        return redisTemplate.opsForValue().get(redisKey);
    }

    /**
     * 订单创建的幂等键：platform + shopId + platformOrderSn
     */
    public String buildOrderCreateKey(String platform, Long shopId, String platformOrderSn) {
        return platform + ":" + shopId + ":" + platformOrderSn;
    }

    /**
     * 库存扣减的幂等键：skuCode + warehouseId + orderId
     */
    public String buildStockDeductKey(String skuCode, Long warehouseId, String orderId) {
        return skuCode + ":" + warehouseId + ":" + orderId;
    }

    /**
     * 订单发货幂等键：orderId
     */
    public String buildShipOrderKey(Long orderId) {
        return "ship:" + orderId;
    }
}
