package com.zanxiang.game.module.sdk.task;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zanxiang.game.module.mybatis.entity.Order;
import com.zanxiang.game.module.sdk.constant.RedisKeyConstant;
import com.zanxiang.game.module.sdk.enums.ExpireTimeEnum;
import com.zanxiang.game.module.sdk.enums.OrderStateEnum;
import com.zanxiang.game.module.sdk.enums.PayTypeEnum;
import com.zanxiang.game.module.sdk.pojo.dto.PlatformOrderDTO;
import com.zanxiang.game.module.sdk.service.IOrderService;
import com.zanxiang.game.module.sdk.service.IPayApplicationService;
import com.zanxiang.game.module.sdk.service.pay.PayBaseService;
import com.zanxiang.game.module.sdk.util.RedisUtil;
import com.zanxiang.game.module.sdk.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Set;

/**
 * @author : lingfeng
 * @time : 2023-01-17
 * @description : 订单过期定时器
 */
@Slf4j
@Component
@RefreshScope
public class OrderExpireTask {

    @Autowired
    private RedisUtil<String> redisUtil;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IPayApplicationService payApplicationService;

    /**
     * 订单过期每分钟检测
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    public void orderExpireCheck() {
        double min = 0.0;
        double max = System.currentTimeMillis();
        //获取缓存订单
        Set<String> paramList = redisUtil.getZSetByScore(RedisKeyConstant.ORDER_EXPIRE, min, max);
        //不存在过期订单
        if (CollectionUtils.isEmpty(paramList)) {
            return;
        }
        //循环处理
        paramList.forEach(param -> {
            log.error("订单过期消费, param : {}", param);
            //缓存锁
            String lock = RedisKeyConstant.ORDER_EXPIRE_LOCK + param;
            //判断订单是否在执行, 设置执行锁 1 分钟
            boolean ifAbsent = redisUtil.setIfAbsent(lock, param, ExpireTimeEnum.ONE_MIN.getTime());
            if (!ifAbsent) {
                return;
            }
            //小程序商城的订单取消
            if (param.contains("_")) {
                payApplicationService.appletStoreCancel(param);
            } else {
                this.orderExpire(param);
            }
            log.error("关闭订单成功, param : {}", param);
            //删除订单列表缓存
            redisUtil.delZSetValue(RedisKeyConstant.ORDER_EXPIRE, param);
            //删除执行缓存锁
            redisUtil.deleteCache(lock);
        });
    }

    private void orderExpire(String orderId) {
        //查询订单信息
        PlatformOrderDTO platformOrderDTO = orderService.getByOrderId(orderId);
        //订单不存在
        if (platformOrderDTO == null) {
            return;
        }
        //已支付订单或者已取消订单不处理
        if (Objects.equals(OrderStateEnum.SUCCESS_PAY.getCode(), platformOrderDTO.getStatus())
                || Objects.equals(OrderStateEnum.CANCEL_PAY.getCode(), platformOrderDTO.getStatus())) {
            return;
        }
        //关闭商户订单
        PayTypeEnum payTypeEnum = PayTypeEnum.getByPayType(platformOrderDTO.getPayWayId().intValue());
        PayBaseService service = SpringUtils.getBean(payTypeEnum.getClazz());
        service.closeOrder(platformOrderDTO);
        //订单状态变更
        orderService.update(new LambdaUpdateWrapper<Order>()
                .set(Order::getStatus, OrderStateEnum.CANCEL_PAY.getCode())
                .eq(Order::getOrderId, orderId));
    }
}
