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.feign.RollbackOrderWeightParam;
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.constant.RabbitKeyConstants;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dao.settle.SettlementOwnerDetailDao;
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.OrderGoods;
import com.clx.performance.param.pc.OrderCancelParam;
import com.clx.performance.param.pc.OrderChildCancelRecordParam;
import com.clx.performance.param.pc.owner.ThawAccountParam;
import com.clx.performance.service.*;
import com.clx.performance.service.child.OrderChildPostService;
import com.clx.performance.vo.app.OrderChildVO;
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;

@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 SettlementOwnerDetailDao settlementOwnerDetailDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ownerConfirmCancelOrderPre(String orderNo) {
        String now = DateUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss").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("货主取消订单失败,原因：远程调用取消订单失败");
            }
            //TODO 注意判断普通单还是网运单 普通单类型 1  网运单 2
            //1网运单 2普通单
            Integer invoiceType = settlementOwnerDetailDao.getInvoiceType(orderNo);
            log.info("invoiceType={}", invoiceType);
            ThawAccountParam thawAccountParam = new ThawAccountParam();

            if (OwnerAccountEnum.OrderChildTypeStatus.ORDINARY.getCode().equals(invoiceType)) {
                thawAccountParam.setOrderType(OwnerAccountEnum.OrderChildTypeStatus.ORDINARY.getCode());
            } else {
                thawAccountParam.setOrderType(OwnerAccountEnum.OrderChildTypeStatus.NETWORK.getCode());
            }
            thawAccountParam.setOrderNo(orderNo);
            log.info("执行解冻账户,参数：{}", JSONUtil.parse(thawAccountParam));
            ownerAccountService.ownerAccountThaw(thawAccountParam);
            this.ownerConfirmCancelProcess(orderNo);
            return;
        }

        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())) {
                    orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
                }
                goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());

                ids.add(orderGoods.getId());
            }
            orderGoodsDao.batchUpdateOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode(),
                    ids);
            //TODO 注意判断普通单还是网运单 普通单类型 1  网运单 2
            //1网运单 2普通单
            Integer invoiceType = settlementOwnerDetailDao.getInvoiceType(orderNo);
            log.info("invoiceType={}", invoiceType);
            ThawAccountParam thawAccountParam = new ThawAccountParam();

            if (OwnerAccountEnum.OrderChildTypeStatus.ORDINARY.getCode().equals(invoiceType)) {
                thawAccountParam.setOrderType(OwnerAccountEnum.OrderChildTypeStatus.ORDINARY.getCode());
            } else {
                thawAccountParam.setOrderType(OwnerAccountEnum.OrderChildTypeStatus.NETWORK.getCode());
            }
            thawAccountParam.setOrderNo(orderNo);
            log.info("执行解冻账户,参数：{}", JSONUtil.parse(thawAccountParam));
            ownerAccountService.ownerAccountThaw(thawAccountParam);

        } 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 {
                    if (orderGoods.getResidueTransportWeight().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())) {
                    orderGoodsTruckBindService.updateCancelTruckBind(orderGoods.getOrderGoodsNo());
                }
                goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());

                orderGoodsDao.updateEntityByKey(update);
            }

        }

        Result<Object> result = orderFeign.updateOrderStatusByOrderNo(orderNo, orderStatusCode);
        if (!result.succeed()) {
            throw new RuntimeException("货主取消订单失败,原因：远程调用取消订单失败");
        }
        this.ownerConfirmCancelProcess(orderNo);


    }

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

        List<OrderGoods> orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
        Map<Integer, BigDecimal> truckDemandMap = new HashMap<>();
        truckDemandMap.put(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode(), BigDecimal.ZERO);
        truckDemandMap.put(TruckDemandEnum.TruckType.OWNER_CAR.getCode(), BigDecimal.ZERO);
        if (!TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode().equals(orderInfoFeignVO.getTruckDemand())) {
            if (OrderEnum.Status.COMPLETED.getCode().equals(orderInfoFeignVO.getOrderStatus())) {
                //已完结
                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);
                    }
                    truckDemandMap.put(orderGoods.getTruckDemand(),
                            truckDemandMap.get(orderGoods.getTruckDemand())
                                    .add(orderGoods.getResidueTransportWeight().add(sum)));

                    orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(sum, sum, orderGoods.getId());
                }

            } else if (OrderEnum.Status.CANCELED.getCode().equals(orderInfoFeignVO.getOrderStatus())) {
                //已取消
                for (OrderGoods orderGoods : orderGoodsList) {
                    truckDemandMap.put(orderGoods.getTruckDemand(),
                            truckDemandMap.get(orderGoods.getTruckDemand())
                                    .add(orderGoods.getResidueTransportWeight()));
                }
            }
            Integer truckDemand = orderInfoFeignVO.getTruckDemand();
            BigDecimal residueWeight = truckDemandMap.get(truckDemand);
            if (residueWeight.compareTo(BigDecimal.ZERO) == 0) {
                log.info("当前订单对应的货单无需吨数回填,订单编号{}", orderNo);
                return;
            }
            //归还吨数
            RollbackOrderWeightParam param = new RollbackOrderWeightParam();
            param.setOrderNo(orderInfoFeignVO.getOrderNo());
            if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                param.setResidueWeight(residueWeight);
                param.setOwnResidueCarryWeight(BigDecimal.ZERO);
                param.setPlatformResidueCarryWeight(residueWeight);
            }
            if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                param.setResidueWeight(residueWeight);
                param.setOwnResidueCarryWeight(residueWeight);
                param.setPlatformResidueCarryWeight(BigDecimal.ZERO);
            }
            orderFeign.rollbackOrderWeight(param);

        } else {
            Map<Integer, BigDecimal> vehicleUsageMap = new HashMap<>();
            vehicleUsageMap.put(1, BigDecimal.ZERO);
            vehicleUsageMap.put(2, BigDecimal.ZERO);
            if (OrderEnum.Status.COMPLETED.getCode().equals(orderInfoFeignVO.getOrderStatus())) {
                //已完结
                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);

                    BigDecimal sum = BigDecimal.ZERO;
                    if (CollectionUtil.isNotEmpty(orderChildMap.get(orderGoodsNo))) {
                        sum = orderChildMap.get(orderGoodsNo).stream()
                                .map(OrderChild::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
                    }
                    vehicleUsageMap.put(orderGoods.getVehicleUsage(),
                            vehicleUsageMap.get(orderGoods.getVehicleUsage())
                                    .add(orderGoods.getResidueTransportWeight().add(sum)));
                    orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(sum, sum, orderGoods.getId());
                }
            } else if (OrderEnum.Status.CANCELED.getCode().equals(orderInfoFeignVO.getOrderStatus())) {
                for (OrderGoods orderGoods : orderGoodsList) {
                    vehicleUsageMap.put(orderGoods.getVehicleUsage(),
                            vehicleUsageMap.get(orderGoods.getVehicleUsage())
                                    .add(orderGoods.getResidueTransportWeight()));
                }

            }
            //归还吨数
            BigDecimal platformResidueSum = vehicleUsageMap.get(1);
            BigDecimal ownResidueSum = vehicleUsageMap.get(2);
            BigDecimal residueSum = platformResidueSum.add(ownResidueSum);
            RollbackOrderWeightParam param = new RollbackOrderWeightParam();
            param.setOrderNo(orderInfoFeignVO.getOrderNo());
            param.setResidueWeight(residueSum);
            param.setPlatformResidueCarryWeight(platformResidueSum);
            param.setOwnResidueCarryWeight(ownResidueSum);
            try {
                Result<Object> result = orderFeign.rollbackOrderWeight(param);
                if (!result.succeed()) {
                    throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "远程调用更新订单余量失败");
                }

                if (!orderFeign.saveOrderSettlementJobRecord(orderNo).succeed()) {
                    throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "货主取消订单失败,原因：远程调用结算单锁定失败");
                }
            } catch (Exception e) {
                throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, e.getMessage());

            }
        }
        //取消订单更新货单剩余吨数
        orderGoodsService.batchUpdateResidueWeight(orderGoodsList);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ownerCancelOrderPre(OrderCancelParam param) {
        String orderNo = param.getOrderNo();
        List<String> childNoList = orderCancelComponent.ownerProcess(param);
        param.setChildNoList(childNoList);
        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 注意判断普通单还是网运单 普通单类型 2  网运单 1

        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 platformCancelOrderPre(OrderCancelParam param) {
        String orderNo = param.getOrderNo();
        List<OrderGoods> orderGoodsList = null;
        Integer orderStatusCode = OrderEnum.Status.CANCELED.getCode();
        String now = DateUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss").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) {
        Map<Integer, BigDecimal> truckDemandMap = new HashMap<>();
        truckDemandMap.put(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode(), BigDecimal.ZERO);
        truckDemandMap.put(TruckDemandEnum.TruckType.OWNER_CAR.getCode(), BigDecimal.ZERO);
        Map<Integer, BigDecimal> vehicleUsageMap = new HashMap<>();
        vehicleUsageMap.put(1, BigDecimal.ZERO);
        vehicleUsageMap.put(2, BigDecimal.ZERO);
        RollbackOrderWeightParam rollbackOrderWeightParam = new RollbackOrderWeightParam();

        String orderNo = param.getOrderNo();
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderNo);
        Integer truckDemand = orderInfoFeign.getTruckDemand();
        List<OrderGoods> orderGoodsList = null;
        switch (param.getCancelType()) {
            case 1: //单纯取消订单及货单
                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);
                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        truckDemandMap.put(orderGoods.getTruckDemand(),
                                truckDemandMap.get(orderGoods.getTruckDemand())
                                        .add(orderGoods.getResidueTransportWeight()));
                    }
                } else {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        vehicleUsageMap.put(orderGoods.getVehicleUsage(),
                                vehicleUsageMap.get(orderGoods.getVehicleUsage())
                                        .add(orderGoods.getResidueTransportWeight()));
                    }
                }
                //归还吨数
                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(truckDemandMap.get(truckDemand));
                    }
                    if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                    }
                } else {
                    BigDecimal platformResidueSum = vehicleUsageMap.get(1);
                    BigDecimal ownResidueSum = vehicleUsageMap.get(2);
                    BigDecimal residueSum = platformResidueSum.add(ownResidueSum);
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    rollbackOrderWeightParam.setResidueWeight(residueSum);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(platformResidueSum);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(ownResidueSum);
                }
                break;
            case 2: //取消未拉运吨数的货单及订单
                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);

                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        truckDemandMap.put(orderGoods.getTruckDemand(),
                                truckDemandMap.get(orderGoods.getTruckDemand())
                                        .add(orderGoods.getResidueTransportWeight()));
                    }
                } else {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        vehicleUsageMap.put(orderGoods.getVehicleUsage(),
                                vehicleUsageMap.get(orderGoods.getVehicleUsage())
                                        .add(orderGoods.getResidueTransportWeight()));
                    }
                }
                //归还吨数
                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(truckDemandMap.get(truckDemand));
                    }
                    if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                    }
                } else {
                    BigDecimal platformResidueSum = vehicleUsageMap.get(1);
                    BigDecimal ownResidueSum = vehicleUsageMap.get(2);
                    BigDecimal residueSum = platformResidueSum.add(ownResidueSum);
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    rollbackOrderWeightParam.setResidueWeight(residueSum);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(platformResidueSum);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(ownResidueSum);
                }
                break;

            case 3: //取消未拉运+未到达货源地吨数
                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));
                }

                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        OrderGoods update = new OrderGoods();
                        update.setId(orderGoods.getId());
                        truckDemandMap.put(orderGoods.getTruckDemand(),
                                truckDemandMap.get(orderGoods.getTruckDemand())
                                        .add(orderGoods.getResidueTransportWeight()));
                        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
                                            )
                            );
                            update.setResidueTransportWeight(orderGoods.getResidueTransportWeight().add(childSum));
                            truckDemandMap.put(orderGoods.getTruckDemand(),
                                    truckDemandMap.get(orderGoods.getTruckDemand())
                                            .add(childSum));
                            orderGoodsDao.updateEntityByKey(update);

                        }
                    }
                } else {
                    for (OrderGoods orderGoods : orderGoodsList) {
                        OrderGoods update = new OrderGoods();
                        update.setId(orderGoods.getId());
                        vehicleUsageMap.put(orderGoods.getVehicleUsage(),
                                vehicleUsageMap.get(orderGoods.getVehicleUsage())
                                        .add(orderGoods.getResidueTransportWeight()));
                        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
                                            )
                            );
                            update.setResidueTransportWeight(orderGoods.getResidueTransportWeight().add(childSum));

                            vehicleUsageMap.put(orderGoods.getTruckDemand(),
                                    vehicleUsageMap.get(orderGoods.getTruckDemand())
                                            .add(childSum));
                            orderGoodsDao.updateEntityByKey(update);
                        }

                    }
                }
                //归还吨数
                if (!orderInfoFeign.getTruckDemand().equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(truckDemandMap.get(truckDemand));
                    }
                    if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                        rollbackOrderWeightParam.setResidueWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setOwnResidueCarryWeight(truckDemandMap.get(truckDemand));
                        rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                    }
                } else {
                    BigDecimal platformResidueSum = vehicleUsageMap.get(1);
                    BigDecimal ownResidueSum = vehicleUsageMap.get(2);
                    BigDecimal residueSum = platformResidueSum.add(ownResidueSum);
                    rollbackOrderWeightParam.setOrderNo(orderNo);
                    rollbackOrderWeightParam.setResidueWeight(residueSum);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(platformResidueSum);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(ownResidueSum);
                }
                break;

            default:
                return;

        }


        if (!orderFeign.rollbackOrderWeight(rollbackOrderWeightParam).succeed()) {
            throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "远程调用更新订单余量失败");
        }

        if (!orderFeign.saveOrderSettlementJobRecord(orderNo).succeed()) {
            throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "货主取消订单失败,原因：远程调用结算单锁定失败");
        }
        //订单取消恢复货单的剩余吨数为0
        orderGoodsService.batchUpdateResidueWeight(orderGoodsList);

        //触发自动冻结的mq消费逻辑
        triggerAutoFreeze(orderInfoFeign.getOwnerUserNo(),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));
        }
    }

    @Override
    public void artificialCancelOrder(String orderChildNo, String remark) {
        LocalDateTime now = LocalDateTime.now();
        OrderChild orderChild = orderChildDao.getByChildNo(orderChildNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        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.getWeight());
        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()
        );
    }

    @Override
    public OrderChildVO findArtificialCancelOrder(String orderChildNo) {
        OrderChildVO artificialCancelOrder = orderChildDao.findArtificialCancelOrder(orderChildNo);
        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;
    }


}