package org.jeecg.modules.redission;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.modules.system.app.entity.AppOrder;
import org.jeecg.modules.system.app.entity.AppOrderProInfo;
import org.jeecg.modules.system.app.service.IAppOrderProInfoService;
import org.jeecg.modules.system.app.service.IAppOrderService;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author wangzhiqiang
 * @Date 2025/8/15
 * @Desc 延迟队列实现订单超时取消
 */
//@Component
@Slf4j
public class RedissonDelayQueue {

    @Resource
    private RedissonConfig redissonConfig;

    @Resource
    private IAppOrderService appOrderService;

    @Resource
    IAppOrderProInfoService appOrderProInfoService;

    private RDelayedQueue<String> delayQueue;
    private RBlockingQueue<String> blockingQueue;

    private RDelayedQueue<String> expireDelayQueue;
    private RBlockingQueue<String> expireBlockingQueue;

//    @PostConstruct
    public void init() {
        initDelayQueue();
//        startDelayQueueConsumer();
//        startExpireDelayQueueConsumer();
    }

    private void initDelayQueue() {
        RedissonClient redissonClient = redissonConfig.redissonClient();

        blockingQueue = redissonClient.getBlockingQueue("OrderTimeOutTask");
        delayQueue = redissonClient.getDelayedQueue(blockingQueue);

        expireBlockingQueue = redissonClient.getBlockingQueue("OrderExpireTask");
        expireDelayQueue = redissonClient.getDelayedQueue(expireBlockingQueue);
    }

    private void startDelayQueueConsumer() {
        new Thread(() -> {
            while (true) {
                try {
                    String task = blockingQueue.take();
                    log.info("接收到延迟任务:{}", task);

                    //执行业务代码
                    String orderId = Arrays.stream(task.split("_")).collect(Collectors.toList()).get(1);
                    AppOrder appOrder = appOrderService.getById(orderId);
                    if(ObjectUtil.isNotEmpty(appOrder)){
                        if (Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_0) && appOrder.getRevision() == 0) {
                            log.info("修改订单：{},支付状态为已取消", orderId);
                            appOrder.setOrderStatus(CommonConstant.ORDER_STATUS_4);
                            appOrderService.updateById(appOrder);
                            //修改子订单状态
                            List<AppOrderProInfo> appOrderProInfoList = appOrderProInfoService.list(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
                            if (CollUtil.isNotEmpty(appOrderProInfoList)){
                                for (AppOrderProInfo appOrderProInfo : appOrderProInfoList) {
                                    appOrderProInfo.setOrderStatus(CommonConstant.ORDER_STATUS_4);
                                    appOrderProInfoService.updateById(appOrderProInfo);
                                }
                            }
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "OrderTimeOutTask-Consumer").start();
    }

    private void startExpireDelayQueueConsumer() {
        new Thread(() -> {
            while (true) {
                try {
                    String task = expireBlockingQueue.take();
                    log.info("接收到延迟任务:{}", task);

                    //执行业务代码
                    String orderId = Arrays.stream(task.split("_")).collect(Collectors.toList()).get(1);
                    AppOrder appOrder = appOrderService.getById(orderId);
                    if(ObjectUtil.isNotEmpty(appOrder)){
                        if (Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_0) && appOrder.getRevision() == 0) {

                            //修改子订单状态
                            List<AppOrderProInfo> appOrderProInfoList = appOrderProInfoService.list(Wrappers.<AppOrderProInfo>lambdaQuery()
                                    .eq(AppOrderProInfo::getOrderId, orderId)
                            );
                            if (CollUtil.isNotEmpty(appOrderProInfoList)){
                                for (AppOrderProInfo appOrderProInfo : appOrderProInfoList) {
                                    if (Objects.equals(appOrderProInfo.getOrderStatus(), CommonConstant.ORDER_STATUS_1)){
                                        log.info("修改订单：{},支付状态为已过期", orderId);
                                        appOrderProInfo.setOrderStatus(CommonConstant.ORDER_STATUS_3);
                                        appOrderProInfoService.updateById(appOrderProInfo);
                                    }
                                }
                            }
                            if (appOrderProInfoList.stream().filter(appOrderProInfo -> Objects.equals(appOrderProInfo.getOrderStatus(),
                                    CommonConstant.ORDER_STATUS_3)).count() == appOrderProInfoList.size()){
                                log.info("修改订单：{},支付状态为已过期", orderId);
                                appOrder.setOrderStatus(CommonConstant.ORDER_STATUS_4);
                                appOrderService.updateById(appOrder);
                            }
                        }

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, "OrderExpireTask-Consumer").start();
    }

    public void offerTask(String task, long seconds) {
        log.info("添加延迟任务:{} 延迟时间:{}s", task, seconds);
        delayQueue.offer(task, seconds, TimeUnit.SECONDS);
    }

    public void offerExpireTask(String task, long days) {
        log.info("添加延迟任务:{} 延迟时间:{}天", task, days);
        expireDelayQueue.offer(task, days, TimeUnit.DAYS);
    }

}
