package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.LawyerConsultationOrder;
import shop.alien.mapper.LawyerConsultationOrderMapper;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.listener.RedisKeyExpirationHandler;
import shop.alien.store.service.OrderExpirationService;

import javax.annotation.PostConstruct;

/**
 * 訂單過期處理服務實現類
 * 
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderExpirationServiceImpl implements OrderExpirationService, CommandLineRunner {

    private final BaseRedisService redisService;
    private final RedisKeyExpirationHandler expirationHandler;
    private final LawyerConsultationOrderMapper orderMapper;

    /**
     * Redis key前綴：訂單支付超時
     */
    private static final String ORDER_PAYMENT_TIMEOUT_PREFIX = "lawyer:order:payment:timeout:";

    /**
     * 默認超時時間：30分鐘
     */
    private static final long DEFAULT_TIMEOUT_SECONDS = 30 * 60;

    /**
     * 初始化時註冊訂單支付超時處理器
     */
    @PostConstruct
    public void init() {
        // 註冊訂單支付超時處理器
        expirationHandler.registerHandler(ORDER_PAYMENT_TIMEOUT_PREFIX, this::handleExpiredOrderKey);
        log.info("訂單支付超時處理器註冊完成，前綴: {}", ORDER_PAYMENT_TIMEOUT_PREFIX);
    }

    @Override
    public void run(String... args) {
        log.info("OrderExpirationService 初始化完成");
    }

    /**
     * 處理過期的訂單key
     * 
     * @param expiredKey 過期的key，格式：order:payment:timeout:{orderId}
     */
    private void handleExpiredOrderKey(String expiredKey) {
        try {
            // 從key中提取訂單ID
            String orderNo = expiredKey.replace(ORDER_PAYMENT_TIMEOUT_PREFIX, "");
            
            log.info("檢測到訂單支付超時，訂單no: {}", orderNo);
            
            // 處理訂單支付超時
            handleOrderPaymentTimeout(orderNo);
        } catch (Exception e) {
            log.error("處理過期訂單key失敗，key: {}", expiredKey, e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleOrderPaymentTimeout(String orderNum) {
        log.info("開始處理訂單支付超時，訂單no: {}", orderNum);
        
        try {
            // 查詢訂單
            LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNum).last("LIMIT 1");
            LawyerConsultationOrder order = orderMapper.selectOne(queryWrapper);
            if (order == null) {
                log.warn("訂單不存在，訂單no: {}", orderNum);
                return;
            }

            // 只處理待支付狀態的訂單
            if (order.getOrderStatus() != null && order.getOrderStatus() == 0) {
                log.info("訂單處於待支付狀態，開始取消訂單，訂單no: {}", orderNum);

                LawyerConsultationOrder lawyerConsultationOrder = new LawyerConsultationOrder();
                // 更新訂單狀態為已取消
                lawyerConsultationOrder.setOrderStatus(4); // 4:已取消
                lawyerConsultationOrder.setId(order.getId());
                lawyerConsultationOrder.setUpdatedTime(new java.util.Date());
                
                int updated = orderMapper.updateById(lawyerConsultationOrder);
                if (updated > 0) {
                    log.info("訂單支付超時，已自動取消訂單，訂單no: {}", orderNum);
                } else {
                    log.error("取消訂單失敗，訂單no: {}", orderNum);
                }
            } else {
                log.info("訂單狀態不是待支付，無需處理，訂單no: {}, 當前狀態: {}", orderNum, order.getOrderStatus());
            }
        } catch (Exception e) {
            log.error("處理訂單支付超時失敗，訂單no: {}", orderNum, e);
            throw e;
        }
    }

    @Override
    public void setOrderPaymentTimeout(String orderNumber, long timeoutSeconds) {
        if (orderNumber == null) {
            log.warn("訂單ID為null，無法設置支付超時監聽");
            return;
        }
        
        String key = ORDER_PAYMENT_TIMEOUT_PREFIX + orderNumber;
        long timeout = timeoutSeconds > 0 ? timeoutSeconds : DEFAULT_TIMEOUT_SECONDS;
        
        // 設置Redis key，帶過期時間
        // 當key過期時，會觸發RedisKeyExpirationListener
        redisService.setString(key, String.valueOf(orderNumber), timeout);
        
        log.info("設置訂單支付超時監聽，訂單NO: {}, 超時時間: {}秒, key: {}", orderNumber, timeout, key);
    }

    /**
     * 取消訂單支付超時監聽（當訂單已支付時調用）
     * 
     * @param orderNumber 訂單NO
     */
    public void cancelOrderPaymentTimeout(String orderNumber) {
        if (orderNumber == null) {
            return;
        }
        
        String key = ORDER_PAYMENT_TIMEOUT_PREFIX + orderNumber;
        redisService.delete(key);
        
        log.info("取消訂單支付超時監聽，訂單ID: {}, key: {}", orderNumber, key);
    }
}

