package com.clx.performance.component;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.clx.order.enums.OrderEnum;
import com.clx.order.enums.VehicleUsageEnum;
import com.clx.order.feign.OrderFeign;
import com.clx.order.param.feign.RollbackOrderWeightParam;
import com.clx.order.vo.feign.FeignOrderVO;
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.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.param.pc.OrderCancelParam;
import com.clx.performance.param.pc.owner.ThawAccountParam;
import com.clx.performance.service.IntegralMqService;
import com.clx.performance.service.OrderChildLogService;
import com.clx.performance.service.OrderGoodsTruckBindService;
import com.clx.performance.service.OwnerAccountService;
import com.clx.performance.service.breakcontract.BreakContractSettlementOwnerService;
import com.clx.performance.service.child.OrderChildPostService;
import com.clx.user.enums.driver.DriverInfoEnum;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import com.msl.common.utils.DateUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Slf4j
@AllArgsConstructor
public class OrderCancelComponent implements InitializingBean {

    private final OrderChildDao orderChildDao;

    private final OrderGoodsDao orderGoodsDao;

    private final OrderGoodsTruckBindService orderGoodsTruckBindService;

    private final GoodsOrderTruckRecordComponent goodsOrderTruckRecordComponent;

    private final OrderFeign orderFeign;

    private final DriverService driverService;

    private final BreakContractSettlementOwnerService breakContractSettlementOwnerService;

    public static Map<Integer, String> statusCodeMap = new HashMap<>();

    private final IntegralMqService integralMqService;

    private final OrderChildLogService orderChildLogService;

    private final OrderChildPostService orderChildPostService;

    private final SettlementOwnerDetailDao settlementOwnerDetailDao;

    private final OwnerAccountService ownerAccountService;

    public List<String> ownerProcess(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();
        List<String> childNoList = new LinkedList<>();

        switch (param.getCancelType()) {
            case 1: //单纯取消订单
                log.info("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());
                        }
                        goodsOrderTruckRecordComponent.deleteTruckRecord(orderGoods.getOrderGoodsNo());

                        ids.add(orderGoods.getId());
                    }
                    orderGoodsDao.batchUpdateOrderGoodsStatus(OrderGoodsStatusEnum.Status.CANCEL.getCode(),
                            ids);
                }
                //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);
                break;
            case 2: //取消未拉运吨数的货单
                log.info("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());

                    orderGoodsDao.updateEntityByKey(update);
                }

                break;

            case 3: //取消未拉运+未到达货源地吨数
                log.info("3:货主取消未拉运+未到达货源地吨数");

                List<OrderChild> orderChildren = orderChildDao.selectResidueWeight(orderNo, OrderChildEnum.Status.ARRIVE_SEND.getCode());
                log.info("执行货主取消未拉运+未到达货源地吨数,当前运单个数" + orderChildren.size());
                for (OrderChild orderChild : orderChildren) {
                    log.info("取消的运单：{}", JSONUtil.parse(orderChild));
                    //释放车辆
                    driverService.updateOrderStatus(orderChild.getDriverUserNo(), DriverInfoEnum.DriverStatus.NO.getCode(), orderChild.getTruckId(), 1);
                    childNoList.add(orderChild.getChildNo());
                    orderChildLogService.saveOrderChildLog(orderChild.getChildNo(),
                            OrderChildEnum.Status.OWNER_CANCEL.getCode(), OrderChildEnum.Status.OWNER_CANCEL.getName(),
                            OrderChildLogEnum.CreateType.OWNER.getCode(), 0L, OrderChildLogEnum.CreateType.OWNER.getMsg()
                    );
                }

                Map<String, List<OrderChild>> orderChildMap = new HashMap<>();
                if (CollectionUtil.isNotEmpty(childNoList)) {
                    log.info("childNoList:{}", childNoList);
                    orderChildDao.batchUpdateOrderChildStatus(
                            OrderChildEnum.Status.OWNER_CANCEL.getCode(), "货主取消",
                            now, now,childNoList);
                    orderChildMap = orderChildren.stream()
                            .collect(Collectors.groupingBy(OrderChild::getOrderGoodsNo));

                }
                orderGoodsList = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);

                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 = BigDecimal.ZERO;
                        for (OrderChild orderChild : orderChildMap.get(orderGoods.getOrderGoodsNo())) {
                            reduce = reduce.add(orderChild.getWeight());
                        }

                        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, "参数有误");

        }

        this.breakContractSettlementOwner(orderNo, orderStatusCode, param.getCancelType());

        log.info("执行货主取消订单更改状态");
        if (!orderFeign.updateOrderStatusByOrderNo(orderNo, orderStatusCode).succeed()) {
            throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "货主取消订单失败,原因：远程调用取消订单失败");
        }
        for (String childNo : childNoList) {
            // 订单取消
            orderChildPostService.orderCancel(childNo);
        }

        return childNoList;

    }

    public void backFillTonnage(OrderGoods orderGoods, BigDecimal weight) {
        if (orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.CANCEL.getCode())
                || orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.COMPLETED.getCode())
        ) {
            Integer truckDemand = orderGoods.getTruckDemand();
            //返回到货单
            orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(weight, weight, orderGoods.getId());

            RollbackOrderWeightParam rollbackOrderWeightParam = new RollbackOrderWeightParam();
            rollbackOrderWeightParam.setOrderNo(orderGoods.getOrderNo());
            rollbackOrderWeightParam.setResidueWeight(weight);

            //归还吨数
            if (!truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(weight);
                } else if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(weight);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                }
            } else {
                if (orderGoods.getVehicleUsage().equals(VehicleUsageEnum.Status.OWN.getCode())) {
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(weight);
                } else {
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(weight);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                }

            }

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

    /**
     * 客服取消归还吨数
     *
     * @param orderGoodsNo
     * @param weight
     */
    public void backFillTonnageForArtificial(String orderGoodsNo, BigDecimal weight) {
        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderGoodsNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.CANCEL.getCode())
                || orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.COMPLETED.getCode())
        ) {
            Integer truckDemand = orderGoods.getTruckDemand();
            //返回到货单
            orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(weight, weight, orderGoods.getId());

            RollbackOrderWeightParam rollbackOrderWeightParam = new RollbackOrderWeightParam();
            rollbackOrderWeightParam.setOrderNo(orderGoods.getOrderNo());
            rollbackOrderWeightParam.setResidueWeight(weight);

            //归还吨数
            if (!truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())) {
                if (truckDemand.equals(TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())) {
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(weight);
                } else if (truckDemand.equals(TruckDemandEnum.TruckType.OWNER_CAR.getCode())) {
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(weight);
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                }
            } else {
                if (orderGoods.getVehicleUsage().equals(VehicleUsageEnum.Status.OWN.getCode())) {
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(BigDecimal.ZERO);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(weight);
                } else {
                    rollbackOrderWeightParam.setPlatformResidueCarryWeight(weight);
                    rollbackOrderWeightParam.setOwnResidueCarryWeight(BigDecimal.ZERO);
                }
            }

            Result<Object> result = orderFeign.rollbackOrderWeight(rollbackOrderWeightParam);
            if (!result.succeed()) {
                throw new ServiceSystemException(PerformanceResultEnum.HTTP_ERROR, "远程调用更新订单余量失败");
            }
        } else {
            //返回到货单
            orderGoodsDao.updateOrderGoodsSetResidueWeightAndAlreadyWeight(weight, weight, orderGoods.getId());

        }
    }


    public void breakContractSettlementOwner(String orderNo, Integer updateStatus, Integer cancelType) {
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderNo);
        Integer orderStatus = orderInfoFeign.getOrderStatus();
        log.info("执行处理违约,订单号：{}, updateStatus:{}, 订单状态{}", orderNo, updateStatus, orderStatus);
        if (OrderEnum.Status.COMPLETED.getCode().equals(updateStatus) || statusCodeMap.containsKey(orderStatus)) {
            try {
                breakContractSettlementOwnerService.saveSettlementOwnerForCancelOrder(orderInfoFeign.getTransportWeight(), orderInfoFeign.getValidFreightPrice(), orderNo, cancelType);
                log.info("执行处理违约完毕");

            } catch (Exception e) {
                log.info("执行处理违约失败{}", e.getMessage());
            }
        }

    }


    @Override
    public void afterPropertiesSet() throws Exception {
        statusCodeMap.put(OrderEnum.Status.QUOTATION_CONFIRMED.getCode(), OrderEnum.Status.QUOTATION_CONFIRMED.getName());
        statusCodeMap.put(OrderEnum.Status.PLATFORM_UNDERTAKING.getCode(), OrderEnum.Status.PLATFORM_UNDERTAKING.getName());
        statusCodeMap.put(OrderEnum.Status.POST_ORDER.getCode(), OrderEnum.Status.POST_ORDER.getName());
        statusCodeMap.put(OrderEnum.Status.ON_ORDER.getCode(), OrderEnum.Status.ON_ORDER.getName());
        statusCodeMap.put(OrderEnum.Status.IN_TRANSIT.getCode(), OrderEnum.Status.IN_TRANSIT.getName());

    }
}
