package com.clx.performance.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.clx.order.enums.OrderEnum;
import com.clx.order.feign.OrderFeign;
import com.clx.order.param.feign.OrderCancelReasonParam;
import com.clx.order.param.mq.FreezeTriggerMqParam;
import com.clx.order.vo.feign.FeignOrderVO;
import com.clx.performance.common.MqWrapper;
import com.clx.performance.component.GoodsOrderTruckRecordComponent;
import com.clx.performance.component.OrderCancelComponent;
import com.clx.performance.component.OwnerAccountComponent;
import com.clx.performance.constant.RabbitKeyConstants;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderChildOperateRecordDao;
import com.clx.performance.dao.OrderChildPoundAuditDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dto.OrderCancelDTO;
import com.clx.performance.enums.*;
import com.clx.performance.extranal.user.DriverService;
import com.clx.performance.extranal.user.OwnerInfoService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderChildOperateRecord;
import com.clx.performance.model.OrderChildPoundAudit;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.param.pc.ArtificialCancelOrderParam;
import com.clx.performance.param.pc.ArtificialCancelOrderQueryParam;
import com.clx.performance.param.pc.OrderCancelParam;
import com.clx.performance.param.pc.OrderChildCancelRecordParam;
import com.clx.performance.service.*;
import com.clx.performance.service.child.OrderChildPostService;
import com.clx.performance.vo.app.OrderChildVO;
import com.clx.performance.vo.mq.OrderTruckBindCancelParam;
import com.clx.performance.vo.pc.OrderChildOperateRecordVO;
import com.clx.user.enums.driver.DriverInfoEnum;
import com.clx.user.enums.owner.FreezeSettingEnum;
import com.clx.user.vo.feign.OwnerInfoFeignVO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import com.msl.common.utils.DateUtils;
import com.msl.user.data.UserSessionData;
import com.msl.user.utils.TokenUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.clx.performance.enums.OrderChildPoundAuditEnum.Status.APPROVED;
import static com.clx.performance.enums.ResultEnum.DATA_ERROR;

@Slf4j
@Service
@AllArgsConstructor
public class OrderCancelServiceImpl implements OrderCancelService {


    private final OrderFeign orderFeign;

    private final OrderChildDao orderChildDao;

    private final OrderGoodsDao orderGoodsDao;

    private final RabbitTemplate rabbitTemplate;

    private final DriverService driverService;

    private final OwnerAccountService ownerAccountService;

    private final OrderGoodsTruckBindService orderGoodsTruckBindService;

    private final GoodsOrderTruckRecordComponent goodsOrderTruckRecordComponent;

    private final OrderCancelComponent orderCancelComponent;

    private final OrderChildLogService orderChildLogService;

    private final OrderChildPostService orderChildPostService;

    private final OrderGoodsService orderGoodsService;

    private final OwnerInfoService ownerInfoService;

    private final OwnerAccountComponent ownerAccountComponent;

    private final OrderChildPoundAuditDao orderChildPoundAuditDao;

    private final OrderChildOperateRecordDao orderChildOperateRecordDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ownerConfirmCancelOrderPre(String orderNo) {
        String now = DateUtils.formatDateTime(LocalDateTime.now()).get();
        List<OrderGoods> orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
        Integer orderStatusCode = OrderEnum.Status.CANCELED.getCode();
        if (CollectionUtil.isEmpty(orderGoodsList)) {
            //未产生货单
            Result<Object> result = orderFeign.updateOrderStatusByOrderNo(orderNo, orderStatusCode);
            if (!result.succeed()) {
                throw new RuntimeException("货主取消订单失败,原因：远程调用取消订单失败");
            }
        } else {
            List<OrderChild> orderChildrenList = orderChildDao.selectResidueWeight(orderNo, null);

            if (CollectionUtil.isEmpty(orderChildrenList)) {
                //说明此刻未产生运单
                List<Integer> ids = new LinkedList<>();
                for (OrderGoods orderGoods : orderGoodsList) {
                    if (orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.DX.getCode())
                    || orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.FLEET_DX.getCode())) {
                        orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
                    }
                    goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());

                    ids.add(orderGoods.getId());
                }
                orderGoodsDao.batchUpdateOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode(),
                        ids);
            } else {
                List<OrderChild> arriveSendChildList = orderChildDao.selectResidueWeight(orderNo, OrderChildEnum.Status.ARRIVE_SEND.getCode());
                orderStatusCode = OrderEnum.Status.COMPLETED.getCode();

                List<String> childNoList = new LinkedList<>();
                for (OrderChild orderChild : arriveSendChildList) {
                    //释放车辆
                    driverService.updateOrderStatus(orderChild.getDriverUserNo(), DriverInfoEnum.DriverStatus.NO.getCode(), orderChild.getTruckId(), 1);
                    childNoList.add(orderChild.getChildNo());
                    orderChildLogService.saveOrderChildLog(orderChild.getChildNo(),
                            OrderChildEnum.Status.PLATFORM_CANCEL.getCode(), OrderChildEnum.Status.PLATFORM_CANCEL.getName(),
                            OrderChildLogEnum.CreateType.PLATFORM.getCode(), 0L, OrderChildLogEnum.CreateType.PLATFORM.getMsg()
                    );
                }

                if (CollectionUtil.isNotEmpty(childNoList)) {
                    orderChildDao.batchUpdateOrderChildStatus(
                            OrderChildEnum.Status.PLATFORM_CANCEL.getCode(), OrderChildEnum.Status.PLATFORM_CANCEL.getName(),
                            now, now,childNoList);
                }

                Map<String, List<OrderChild>> orderChildMap = orderChildrenList.stream()
                        .collect(Collectors.groupingBy(OrderChild::getOrderGoodsNo));

                for (OrderGoods orderGoods : orderGoodsList) {
                    OrderGoods update = new OrderGoods();
                    update.setId(orderGoods.getId());
                    List<OrderChild> orderChildren = orderChildMap.get(orderGoods.getOrderGoodsNo());
                    if (CollectionUtil.isEmpty(orderChildren)) {
                        //没有运单，直接是取消
                        update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode());
                    } else {
                        BigDecimal residueTransportWeight = orderGoodsService.calcOrderGoodsResidueWeight
                                (orderGoods.getExtractWeight(),orderGoods.getAlreadyTransportWeight());

                        if (residueTransportWeight.compareTo(BigDecimal.ZERO) != 0) {
                            //货单还有余量，是已完结
                            update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.COMPLETED.getCode());
                        } else {
                            List<OrderChild> orderChildrenListComplete = orderChildDao.selectOrderChildListByOrderGoodsNoAndStatusGE(orderGoods.getOrderGoodsNo(), OrderChildEnum.Status.ARRIVE_SEND.getCode());
                            if (CollectionUtil.isNotEmpty(orderChildrenListComplete)) {
                                //没有余量,需要判断已完成的运单量是不等于货单的全部提取量，等于则是已完成，否则是已完结
                                BigDecimal reduce = orderChildrenListComplete.stream().map(OrderChild::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
                                if (reduce.compareTo(orderGoods.getExtractWeight()) == 0) {
                                    update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.SUCCESS.getCode());
                                } else {
                                    update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.COMPLETED.getCode());
                                }
                            } else {
                                //虽然没有余量，但是可以取消的运单都是未到达货源地的
                                update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode());
                            }
                        }
                    }

                    if (orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.DX.getCode())
                    || orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.FLEET_DX.getCode())) {
                        orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
                    }
                    goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());

                    orderGoodsDao.updateEntityByKey(update);
                }

            }
        }
        Result<Object> result = orderFeign.updateOrderStatusByOrderNo(orderNo, orderStatusCode);
        if (!result.succeed()) {
            throw new ServiceSystemException( PerformanceResultEnum.HTTP_ERROR,"货主取消订单失败,原因：远程调用取消订单失败");
        }
        //进行解冻账户
        ownerAccountComponent.thawOwnerAccountByOrderNo(orderNo);

        OrderTruckBindCancelParam bindCancelParam = new OrderTruckBindCancelParam();
        bindCancelParam.setOrderNo(orderNo);
        Message message = MessageBuilder.withBody(JSONUtil.parse(bindCancelParam).toString().getBytes()).build();

        message.getMessageProperties().setHeader("x-delay", 2000);

        //执行解绑自有车辆处理逻辑，将绑定记录正常改为取消
        rabbitTemplate.send(
                RabbitKeyConstants.ORDER_TRUCK_BIND_LAZY_EXCHANGE, RabbitKeyConstants.ORDER_TRUCK_BIND_LAZY_ROUTE_KEY, message
        );
        this.ownerConfirmCancelProcess(orderNo);

    }

    @Override
    public void ownerConfirmCancelProcess(String orderNo) {
        log.info("开始执行订单取消操作");
        FeignOrderVO orderInfoFeignVO = orderFeign.getOrderInfoFeign(orderNo);


        if (OrderEnum.Status.COMPLETED.getCode().equals(orderInfoFeignVO.getOrderStatus())) {

            List<OrderGoods> orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);

            //已完结
            List<OrderChild> orderChildrenList = orderChildDao.selectResidueWeight(orderNo, OrderChildEnum.Status.ARRIVE_SEND.getCode());
            Map<String, List<OrderGoods>> orderGoodsMap = orderGoodsList.stream()
                    .collect(Collectors.groupingBy(OrderGoods::getOrderGoodsNo));

            Map<String, List<OrderChild>> orderChildMap = orderChildrenList.stream()
                    .collect(Collectors.groupingBy(OrderChild::getOrderGoodsNo));

            for (Map.Entry<String, List<OrderGoods>> entry : orderGoodsMap.entrySet()) {
                String orderGoodsNo = entry.getKey();
                OrderGoods orderGoods = entry.getValue().get(0);
                List<OrderChild> orderChildren = orderChildMap.get(orderGoodsNo);
                BigDecimal sum = BigDecimal.ZERO;
                if (CollectionUtil.isNotEmpty(orderChildren)) {
                    sum = orderChildren.stream()
                            .map(OrderChild::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
                }
                orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(sum, sum, orderGoods.getId());
            }
        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer ownerCancelOrderPre(OrderCancelParam param) {
        String orderNo = param.getOrderNo();

        OrderCancelDTO orderCancelDTO = orderCancelComponent.ownerProcess(param);
        param.setChildNoList(orderCancelDTO.getChildNoList());
        OrderCancelReasonParam orderCancelReasonParam = new OrderCancelReasonParam();
        orderCancelReasonParam.setOrderNo(orderNo);
        orderCancelReasonParam.setReason(param.getCancelReason());
        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        orderCancelReasonParam.setCreateNo(loginUserInfo.getUserNo());
        orderCancelReasonParam.setCreateName(loginUserInfo.getUserName());
        orderFeign.orderCancelReason(orderCancelReasonParam);


        log.info("执行货主订单取消前置：更改相关状态完毕，开始执行吨数回填，发送MQ消息,订单No {}", orderNo);

        Message message = MessageBuilder.withBody(JSONUtil.parse(param).toString().getBytes()).build();
        rabbitTemplate.send(
                RabbitKeyConstants.ORDER_CANCEL_EXCHANGE, RabbitKeyConstants.ORDER_CANCEL_ROUTE_KEY, message
        );

        OrderTruckBindCancelParam bindCancelParam = new OrderTruckBindCancelParam();
        bindCancelParam.setOrderNo(orderNo);
        Message message2 = MessageBuilder.withBody(JSONUtil.parse(bindCancelParam).toString().getBytes()).build();

        message2.getMessageProperties().setHeader("x-delay", 2000);
        //执行解绑自有车辆处理逻辑，将绑定记录正常改为取消
        rabbitTemplate.send(
                RabbitKeyConstants.ORDER_TRUCK_BIND_LAZY_EXCHANGE, RabbitKeyConstants.ORDER_TRUCK_BIND_LAZY_ROUTE_KEY, message2
        );

        return orderCancelDTO.getStatus();
    }

//    /**
//     * 平台取消订单前置(只修改订单相关状态)
//     *
//     * @param param
//     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public void platformCancelOrderPre(OrderCancelParam param) {
//        String orderNo = param.getOrderNo();
//        List<OrderGoods> orderGoodsList = null;
//        Integer orderStatusCode = OrderEnum.Status.CANCELED.getCode();
//        String now = DateUtils.formatDateTime(LocalDateTime.now()).get();
//        switch (param.getCancelType()) {
//            case 1: //单纯取消订单
//                if (CollectionUtil.isNotEmpty(orderChildDao.getOrderChildByOrderNo(orderNo))) {
//                    throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "当前订单已发生变化,请重新选择取消方式");
//                }
//                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
//
//                if (CollectionUtil.isNotEmpty(orderGoodsList)) {
//                    List<Integer> ids = new LinkedList<>();
//                    for (OrderGoods orderGoods : orderGoodsList) {
//                        if (orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.DX.getCode())) {
//                            orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
//                        }
//                        ids.add(orderGoods.getId());
//                        goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());
//
//                    }
//                    orderGoodsDao.batchUpdateOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode(),
//                            ids);
//                }
//                break;
//            case 2: //取消未拉运吨数的货单
//                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
//
//                for (OrderGoods orderGoods : orderGoodsList) {
//                    OrderGoods update = new OrderGoods();
//                    update.setId(orderGoods.getId());
//                    //提取和剩余吨数一样,代表一直没人拉
//                    if (orderGoods.getResidueTransportWeight().compareTo(orderGoods.getExtractWeight()) == 0) {
//                        update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode());
//                    } else {
//                        orderStatusCode = OrderEnum.Status.COMPLETED.getCode();
//                        update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.COMPLETED.getCode());
//                    }
//                    if (orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.DX.getCode())) {
//                        orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
//                        goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());
//                    }
//                    goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());
//
//                    orderGoodsDao.updateEntityByKey(update);
//                }
//                break;
//
//            case 3: //取消未拉运+未到达货源地吨数
//                List<OrderChild> orderChildren = orderChildDao.selectResidueWeight(orderNo, OrderChildEnum.Status.ARRIVE_SEND.getCode());
//                if (CollectionUtil.isEmpty(orderChildren)) {
//                    throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "当前订单已发生变化,请重新选择取消方式");
//                }
//                List<String > childNoList = new LinkedList<>();
//                for (OrderChild orderChild : orderChildren) {
//                    //释放车辆
//                    driverService.updateOrderStatus(orderChild.getDriverUserNo(), DriverInfoEnum.DriverStatus.NO.getCode(), orderChild.getTruckId(), 1);
//                    childNoList.add(orderChild.getChildNo());
//                }
//                if (CollectionUtil.isNotEmpty(childNoList)) {
//                    orderChildDao.batchUpdateOrderChildStatus(
//                            OrderChildEnum.Status.OWNER_CANCEL.getCode(), "平台取消",
//                            now, now, childNoList);
//                }
//
//                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
//                Map<String, List<OrderChild>> orderChildMap = orderChildren.stream()
//                        .collect(Collectors.groupingBy(OrderChild::getOrderGoodsNo));
//
//                for (OrderGoods orderGoods : orderGoodsList) {
//                    OrderGoods update = new OrderGoods();
//                    update.setId(orderGoods.getId());
//                    if (CollectionUtil.isEmpty(orderChildMap.get(orderGoods.getOrderGoodsNo()))) {
//                        update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode());
//                    } else {
//                        BigDecimal reduce = orderChildMap.get(orderGoods.getOrderGoodsNo())
//                                .stream().map(OrderChild::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
//                        //当前产生可取消运单的吨数加货单剩余吨数如果等于货单提取的吨数,那么就是已取消
//                        if (orderGoods.getExtractWeight().compareTo(orderGoods.getResidueTransportWeight().add(reduce)) == 0) {
//                            update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode());
//                        } else {
//                            orderStatusCode = OrderEnum.Status.COMPLETED.getCode();
//                            update.setOrderGoodsStatus(OrderGoodsStatusEnum.Status.COMPLETED.getCode());
//                        }
//                    }
//
//                    if (orderGoods.getPendingOrderWay().equals(PendingOrderWayStatusEnum.Status.DX.getCode())) {
//                        orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
//                    }
//                    goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());
//
//                    orderGoodsDao.updateEntityByKey(update);
//                }
//
//                break;
//
//            default:
//                throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "参数有误");
//
//        }
//
//        log.info("记录订单取消原因");
//        OrderCancelReasonParam orderCancelReasonParam = new OrderCancelReasonParam();
//        orderCancelReasonParam.setOrderNo(orderNo);
//        orderCancelReasonParam.setReason(param.getCancelReason());
//        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
//        orderCancelReasonParam.setCreateNo(loginUserInfo.getUserNo());
//        orderCancelReasonParam.setCreateName(loginUserInfo.getUserName());
//        orderFeign.orderCancelReason(orderCancelReasonParam);
//        //TODO 注意判断普通单还是网运单 普通单类型 1  网运单 2
//
//        log.info("执行订单状态更改");
//        if (!orderFeign.updateOrderStatusByOrderNo(orderNo, orderStatusCode).succeed()) {
//            throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "货主取消订单失败,原因：远程调用取消订单失败");
//        }
//        log.info("执行承运端订单取消前置：更改相关状态完毕，开始执行吨数回填，发送MQ消息,订单No {}", orderNo);
//
//        Message message = MessageBuilder.withBody(JSONUtil.parse(param).toString().getBytes()).build();
//        rabbitTemplate.send(
//                RabbitKeyConstants.ORDER_CANCEL_EXCHANGE, RabbitKeyConstants.ORDER_CANCEL_ROUTE_KEY, message
//        );
//    }

    /**
     * 执行订单取消后归还吨数
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderCancelProcess(OrderCancelParam param) {
        String orderNo = param.getOrderNo();
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderNo);
        switch (param.getCancelType()) {
            case 1: //单纯取消订单及货单
                getOrderGoods(orderNo);
                break;
            case 2: //取消未拉运吨数的货单及订单
                getGoods(orderNo);
                break;
            case 3: //取消未拉运+未到达货源地吨数
                getOrderGoods(param, orderNo);
                break;
            default:
                return;

        }

        //触发自动冻结的mq消费逻辑
        triggerAutoFreeze(orderInfoFeign.getOwnerUserNo(),orderNo);

    }

    private List<OrderGoods> getOrderGoods(OrderCancelParam param, String orderNo) {
        List<OrderGoods> orderGoodsList;
        orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
        Map<String, List<OrderChild>> orderChildMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(param.getChildNoList())) {
            List<OrderChild> orderChildren = orderChildDao.selectInOrderChildNoList(param.getChildNoList());
            orderChildMap = orderChildren.stream().collect(Collectors.groupingBy(OrderChild::getOrderGoodsNo));
        }
        for (OrderGoods orderGoods : orderGoodsList) {
            OrderGoods update = new OrderGoods();
            update.setId(orderGoods.getId());
            if (CollectionUtil.isNotEmpty(orderChildMap.get(orderGoods.getOrderGoodsNo()))) {
                BigDecimal childSum = orderChildMap.get(orderGoods.getOrderGoodsNo()).stream()
                        .map(OrderChild::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
                update.setAlreadyTransportWeight(orderGoods.getAlreadyTransportWeight().subtract(childSum)
                );
                orderGoodsDao.updateEntityByKey(update);
            }
        }
        return orderGoodsList;
    }

    private List<OrderGoods> getGoods(String orderNo) {
        return orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
    }

    private List<OrderGoods> getOrderGoods(String orderNo) {
        return orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
    }

    //订单取消增加自动冻结的消息触发
    private void triggerAutoFreeze(Long ownerUserNo,String orderNo){
        try{
            OwnerInfoFeignVO ownerInfo = ownerInfoService.getOwnerInfo(ownerUserNo);
            //充值成功并且当前货主是冻结方式是自动冻结，则触发自动冻结的mq监听
            if(Objects.equals(ownerInfo.getFreezeSetting(), FreezeSettingEnum.AUTO.getCode())){
                log.info("货主取消订单,发送自动冻结的mq消息,货主编号：{}，订单编号：{}",ownerUserNo,orderNo);
                FreezeTriggerMqParam mq = new FreezeTriggerMqParam();
                mq.setUserNo(ownerUserNo);
                Message message = MessageBuilder.withBody(JSON.toJSONString(new MqWrapper<>(mq)).getBytes()).build();
                //设置延时5秒处理，防止事务未提交
                message.getMessageProperties().setHeader("x-delay", 5000);
                rabbitTemplate.send(RabbitKeyConstants.FREEZE_TRIGGER_EXCHANGE, RabbitKeyConstants.FREEZE_TRIGGER_ROUTING_KEY,message);
            }
        }catch (Exception e){
            log.warn("货主取消订单，自动冻结发生异常：{}", ExceptionUtils.getStackTrace(e));
        }
    }

    /**
     * 客服取消订单
     * @param orderChildNo
     * @param remark
     */
    @Override
    public void artificialCancelOrder(String orderChildNo, String remark) {
        //磅单如果审核通过，该运单不允许取消
        List<OrderChildPoundAudit> poundAuditList = orderChildPoundAuditDao.getPoundAuditList(orderChildNo);
        if (poundAuditList.stream().anyMatch(item->APPROVED.getCode().equals(item.getStatus()))) {
            throw new ServiceSystemException(DATA_ERROR, "该运单磅单已审核通过，不允许取消");
        }

        LocalDateTime now = LocalDateTime.now();
        OrderChild orderChild = orderChildDao.getByChildNo(orderChildNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        //运单状态不在【装车成功】【前往目的地】【到达目的地】【收货待确认】范围中，不允许取消
        if (!Arrays.asList(OrderChildEnum.Status.LOAD.getCode(),
                        OrderChildEnum.Status.GO_TO_SEND.getCode(),
                        OrderChildEnum.Status.ARRIVE_SEND.getCode(),
                        OrderChildEnum.Status.UNLOAD.getCode())
                .contains(orderChild.getStatus())) {
            log.info("运单:{} 状态:{}不在【装车成功】【前往目的地】【到达目的地】【收货待确认】范围中，不允许取消", orderChildNo, orderChild.getStatus());
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_CANCEL_FORBID, "不可操作");
        }

        OrderChild update = new OrderChild();
        update.setId(orderChild.getId());
        update.setStatus(OrderChildEnum.Status.ARTIFICIAL_CANCEL.getCode());
        update.setCancelRemark(remark);
        update.setCancelTime(now);
        update.setFinishTime(now);
        orderChildDao.updateEntityByKey(update);

        orderCancelComponent.backFillTonnageForArtificial(orderChild.getOrderGoodsNo(), orderChild.getLoadNet());
        goodsOrderTruckRecordComponent.releaseAllDriverCard(orderChild.getOrderGoodsNo(), orderChild.getTruckNo());
        driverService.updateOrderStatus(orderChild.getDriverUserNo(), DriverInfoEnum.DriverStatus.NO.getCode(), orderChild.getTruckId(), 1);

        // 运单取消
        orderChildPostService.orderChildCancelByArtificial(orderChildNo);

        // 保存操作记录
        orderChildLogService.saveOrderChildLog(orderChild.getChildNo(),
                OrderChildEnum.Status.ARTIFICIAL_CANCEL.getCode(), OrderChildEnum.Status.ARTIFICIAL_CANCEL.getName(),
                OrderChildLogEnum.CreateType.ARTIFICIAL.getCode(), 0L, OrderChildLogEnum.CreateType.ARTIFICIAL.getMsg()
        );

        // 保存运单处理记录
        saveOrderChildOperateRecord(orderChild, OrderChildEnum.OperateRecordType.CANCEL_ORDER, remark);
    }

    @Override
    public OrderChildVO findArtificialCancelOrder(ArtificialCancelOrderQueryParam param) {
        //检查参数
        param.checkParam();
        OrderChildVO artificialCancelOrder = orderChildDao.findArtificialCancelOrder(param);
        if (artificialCancelOrder == null) {
            return null;
        }
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(artificialCancelOrder.getOrderNo());
        if (orderInfoFeign != null) {
            artificialCancelOrder.setGoodTypeName(orderInfoFeign.getGoodsTypeName());
        }
        return artificialCancelOrder;
    }

    @Override
    public IPage<OrderChildVO> orderChildCancelRecord(OrderChildCancelRecordParam param) {
        IPage<OrderChildVO> page = orderChildDao.orderChildCancelRecord(param);
        if (!page.getRecords().isEmpty()) {
            String orderNo = page.getRecords().get(0).getOrderNo();
            FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderNo);
            for (OrderChildVO record : page.getRecords()) {
                record.setGoodTypeName(orderInfoFeign.getGoodsTypeName());
            }
        }
        return page;
    }

    @Override
    public IPage<OrderChildOperateRecordVO> orderChildOperateRecord(OrderChildCancelRecordParam param) {
        return orderChildOperateRecordDao.orderChildOperateRecord(param);
    }

    @Override
    // todo ：jiangwujie 事务判断 ，其他也检查一下
    public void removeLoadLimit(ArtificialCancelOrderParam param) {
        OrderChild orderChild = orderChildDao.getByChildNo(param.getOrderChildNo()).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        //判断运单状态【已接单】【前往货源地】【到达货源地】时可对该运单解除装车限制，否则toast：不可操作
        if (!Arrays.asList(OrderChildEnum.Status.CREATED.getCode(),
                        OrderChildEnum.Status.GO_TO_SEND.getCode(),
                        OrderChildEnum.Status.ARRIVE_SEND.getCode())
                .contains(orderChild.getStatus())) {
            log.info("运单:{} 状态:{}不在【已接单】【前往货源地】【到达货源地】范围中，不允许解除装车限制", param.getOrderChildNo(), orderChild.getStatus());
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_CANCEL_FORBID, "不可操作");
        }

        OrderChild update = new OrderChild();
        update.setId(orderChild.getId());
        update.setRemoveLoadLimitStatus(OrderChildEnum.RemoveLoadLimitStatus.REMOVED.getCode());
        orderChildDao.updateEntityByKey(update);

        //保存运单处理记录
        saveOrderChildOperateRecord(orderChild, OrderChildEnum.OperateRecordType.REMOVE_LIMIT, param.getRemark());

        //保存运单操作记录
        orderChildLogService.saveOrderChildLog(orderChild.getChildNo(),
                orderChild.getStatus(), OrderChildEnum.OperateRecordType.REMOVE_LIMIT.getMsg(),
                OrderChildLogEnum.CreateType.ARTIFICIAL.getCode(), 0L, OrderChildLogEnum.CreateType.ARTIFICIAL.getMsg()
        );
    }

    private void saveOrderChildOperateRecord(OrderChild orderChild, OrderChildEnum.OperateRecordType type, String remark) {
        OrderChildOperateRecord record = new OrderChildOperateRecord();
        record.setChildNo(orderChild.getChildNo());
        record.setType(type.getCode());
        record.setTruckNo(orderChild.getTruckNo());
        record.setDriverName(orderChild.getDriverName());
        record.setDriverMobile(orderChild.getDriverMobile());
        record.setSendAddress(orderChild.getSendAddress());
        record.setReceiveAddress(orderChild.getReceiveAddress());
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderChild.getOrderNo());
        if (orderInfoFeign != null) {
            record.setGoodTypeName(orderInfoFeign.getGoodsTypeName());
        }
        record.setRemark(remark);
        record.setOperateTime(LocalDateTime.now());
        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        record.setOperator(loginUserInfo.getUserName());
        record.setCreatedTime(LocalDateTime.now());
        record.setModifiedTime(LocalDateTime.now());
        orderChildOperateRecordDao.saveEntity(record);
    }


}