package com.sqx.scheduler.order;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.order.entity.TbOrder;
import com.sqx.modules.order.service.AppOrderService;
import com.sqx.scheduler.config.SchedulerLock;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单定时任务
 *
 * @author : codingliang
 * @date : 2024-08-19 20:42
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderScheduler {

    private final RedissonClient redissonClient;
    private final AppOrderService orderService;
    private final CommonInfoService commonInfoService;

    /**
     * 预约订单自动接单
     * 5分钟运行一次
     */
    @Async
    @Scheduled(cron = "0 */5 * * * ?")
    public void reservationAutoReceivingOrder() {
        RLock lock = redissonClient.getLock(SchedulerLock.ORDER_OF_RESERVATION_AUTO_RECEIVING_LOCK);
        lock.lock();
        try {
            log.info("预约订单自动接单任务开始运行");
            List<Long> orderIds = orderService.getCurWaitReceivingOrderIds();
            if (CollUtil.isEmpty(orderIds)) {
                log.info("没有符合条件的预约订单，预约订单自动接单任务运行....");
                return;
            }

            List<TbOrder> waitOrders = orderIds.stream().map(orderId -> {
                TbOrder waitOrder = new TbOrder();
                waitOrder.setOrderId(orderId);
                waitOrder.setStatus(6);

                return waitOrder;
            }).collect(Collectors.toList());

            for (TbOrder waitOrder : waitOrders) {
                log.info("预约订单id：{}，正在自动接单", waitOrder.getOrderId());
                try {
                    orderService.updateOrder(waitOrder);
                    log.info("预约订单id：{}，自动接单成功", waitOrder.getOrderId());
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("预约单id:{},自动接单失败，失败原因：{}", waitOrder.getOrderId(), e.getMessage());
                }
            }

            log.info("预约订单自动接单任务运行成功");
        } catch (Exception e) {
            log.error("预约订单自动接单任务运行失败失败原因：{}", e.getMessage());
        } finally {
            lock.unlock();
        }
    }

    /**
     * 制作中订单自动制作完成
     * 每分钟30秒时运行一次
     */
    @Async
    @Scheduled(cron = "30 */2 * * * ?")
    public void prodIngOrderAutoCompleted(){
        try {
            log.info("自动制作完成制作中订单任务开始运行");
            // 获取配置：是否开启制作中订单自动完成
            String value = commonInfoService.findOne(418).getValue();
            if("是".equals(value)){
                String minute = commonInfoService.findOne(419).getValue();
                LocalDateTime minusMinutes = LocalDateTime.now().minusMinutes(Long.valueOf(minute));

                // 获取制作中状态的订单列表
                List<TbOrder> orders = orderService.getProdIngOrders(minusMinutes);
                if (CollUtil.isEmpty(orders)) {
                    log.info("当前时间段没有需要自动制作完成的订单");
                } else {
                    // 订单随机排序
                    Collections.shuffle(orders);
                    for (TbOrder order: orders){
                        try {
                            log.info("订单：{}，开始自动制作完成", order.getOrderId());
                            order.setStatus(3);
                            orderService.updateOrder(order);
                            log.info("订单：{}，自动制作完成", order.getOrderId());
                        } catch (Exception e){
                            e.printStackTrace();
                            log.error("订单：{}，自动完成异常，异常原因：【{}】", order.getOrderId(), e);
                        }
                    }
                }
            }
            log.info("自动制作完成制作中订单任务运行成功");
        } catch (Exception e) {
            log.error("制作中订单自动制作完成任务运行失败失败原因：【{}】", e);
        }
    }

    /**
     * 自动完成订单
     * 每30s运行一次
     */
    @Async
    @Scheduled(cron = "45 */1 * * * ?")
    public void autoFinishOrder() {
        RLock lock = redissonClient.getLock(SchedulerLock.ORDER_OF_WAIT_DELIVERY_AUTO_FINISH_LOCK);
        lock.lock();
        try {
            log.info("自动完成订单任务开始运行");
            CommonInfo one = commonInfoService.findOne(268);
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 查询所有 待取餐/派送中 状态的订单
            QueryWrapper<TbOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 3);
            List<TbOrder> orders = orderService.list(queryWrapper);

            for (TbOrder order: orders) {
                try {
                    LocalDateTime updateTime = LocalDateTime.parse(order.getUpdateTime(), df);
                    // 计算当前订单什么时候超时完成
                    LocalDateTime overDateTime = updateTime.plusHours(Integer.parseInt(one.getValue()));
                    if (LocalDateTime.now().isAfter(overDateTime)) {
                        log.info("订单id：{}，开始自动完成", order.getOrderId());
                        orderService.accomplishOrders(order.getOrderId(),2);
                        log.info("订单id：{}，完成自动完成", order.getOrderId());
                    }
                } catch (Exception e) {
                    log.error("订单id：{}，开始自动完成失败，失败原因【{}】", order.getOrderId(), e);
                }
            }
            log.info("自动完成订单任务运行成功");
        } catch (Exception e) {
            log.info("自动完成订单任务运行异常，异常", e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 自动更改超时订单
     * 每3分钟运行一次
     */
    @Async
    @Scheduled(cron = "0 */3 * * * ?")
    public void changeTimeOutOrder() {
        RLock lock = redissonClient.getLock(SchedulerLock.TIME_OUT_LOCK);
        lock.lock();
        try {
            log.info("超时订单自动取消任务开始运行");
//            查询所有超时时间不为空的待结账订单
            LambdaQueryWrapper<TbOrder> wrapper=new LambdaQueryWrapper<>();
            wrapper.eq(TbOrder::getStatus,0)
                    .isNotNull(TbOrder::getTimeOut);
            List<TbOrder> orderList = orderService.list(wrapper);

            if (orderList.size()==0) {
                log.info("没有符合条件的超时订单，超时订单自动取消任务运行....");
                return;
            }

            long time = new Date().getTime();
            ArrayList<TbOrder> orders = new ArrayList<>();
            for (TbOrder tbOrder : orderList) {
                Long timeOut = tbOrder.getTimeOut();
                if (time>timeOut) {
                    tbOrder.setStatus(5);
                    orders.add(tbOrder);
                }
            }

            orderService.updateBatchById(orders);

            log.info("超时订单自动取消运行成功");
        } catch (Exception e) {
            log.error("超时订单自动取消任务运行失败失败原因：{}", e.getMessage());
        } finally {
            lock.unlock();
        }
    }
}
