package com.clx.performance.service.impl;

import com.clx.order.enums.VehicleUsageEnum;
import com.clx.order.vo.feign.FeignOrderInfoVO;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.enums.*;
import com.clx.performance.extranal.user.OrderService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.service.OrderWeightService;
import com.clx.performance.vo.feign.OrderExtractWeightVO;
import com.msl.common.exception.ServiceSystemException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName OrderWeightServiceImpl
 * @Description
 * @Author kavin
 * @Date 2024/8/5 11:52
 * @Version 1.0
 */

@Slf4j
@Service
@AllArgsConstructor
public class OrderWeightServiceImpl implements OrderWeightService {

    private final OrderService orderService;
    private final OrderGoodsDao orderGoodsDao;
    private final OrderChildDao orderChildDao;
    @Override
    public OrderExtractWeightVO getOrderCanExtractWeight(String orderNo) {
        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(orderNo).orElseThrow(
                PerformanceResultEnum.DATA_NOT_FIND);


        List<OrderGoods> orderGoodsList = orderGoodsDao.listByField(OrderGoods::getOrderNo, orderNo);
        if(CollectionUtils.isEmpty(orderGoodsList)){
            BigDecimal canExtractWeight = Objects.nonNull(orderInfo.getPlatformCarryWeight())?
                    orderInfo.getPlatformCarryWeight():BigDecimal.ZERO.add(
                            Objects.nonNull(orderInfo.getOwnCarryWeight())?
                    orderInfo.getOwnCarryWeight():BigDecimal.ZERO);
            return  OrderExtractWeightVO.builder().transportWeight(orderInfo.getTransportWeight())
                    .truckDemand(orderInfo.getTruckDemand())
                    .ownCarryWeight(orderInfo.getOwnCarryWeight())
                    .platformCarryWeight(orderInfo.getPlatformCarryWeight())
                    .ownCanExtractWeight(orderInfo.getOwnCarryWeight())
                    .platCanExtractWeight(orderInfo.getPlatformCarryWeight())
                    .canExtractWeight(canExtractWeight)
                    .build();
        }
        //已发布的自有车辆吨数
        BigDecimal ownOrderGoodsWeight = BigDecimal.ZERO;
        //已发布的平台车辆吨数
        BigDecimal platOrderGoodsWeight = BigDecimal.ZERO;

        for (OrderGoods item : orderGoodsList) {
            BigDecimal weight = calcOrderGoodsRealExtractWeight(item);
            if(Objects.equals(item.getVehicleUsage(), VehicleUsageEnum.Status.OWN.getCode())){
                ownOrderGoodsWeight = ownOrderGoodsWeight.add(weight);
            }
            if(Objects.equals(item.getVehicleUsage(), VehicleUsageEnum.Status.PLATFORM.getCode())){
                platOrderGoodsWeight = platOrderGoodsWeight.add(weight);
            }
        }


        if(Objects.equals(orderInfo.getTruckDemand(), TruckDemandEnum.TruckType.PLATFORM_CAR.getCode())){
            return  OrderExtractWeightVO.builder().transportWeight(orderInfo.getTransportWeight())
                    .truckDemand(orderInfo.getTruckDemand())
                    .platformCarryWeight(orderInfo.getPlatformCarryWeight())
                    .platCanExtractWeight(orderInfo.getTransportWeight().subtract(platOrderGoodsWeight))
                    .ownCarryWeight(BigDecimal.ZERO)
                    .ownCanExtractWeight(BigDecimal.ZERO)
                    .canExtractWeight(orderInfo.getTransportWeight().subtract(platOrderGoodsWeight))
                    .build();
        }
        if(Objects.equals(orderInfo.getTruckDemand(), TruckDemandEnum.TruckType.OWNER_CAR.getCode())){
            return  OrderExtractWeightVO.builder().transportWeight(orderInfo.getTransportWeight())
                    .truckDemand(orderInfo.getTruckDemand())
                    .ownCarryWeight(orderInfo.getOwnCarryWeight())
                    .ownCanExtractWeight(orderInfo.getTransportWeight().subtract(ownOrderGoodsWeight))
                    .platformCarryWeight(BigDecimal.ZERO)
                    .platCanExtractWeight(BigDecimal.ZERO)
                    .canExtractWeight(orderInfo.getTransportWeight().subtract(ownOrderGoodsWeight))
                    .build();
        }
        if(Objects.equals(orderInfo.getTruckDemand(), TruckDemandEnum.TruckType.PLATFORM_ANY_CAR.getCode())){
            //因为自有车辆的货单必须一次性全部提取，所有只要自有车辆吨数，剩下的吨数则为平台可提取吨数
            BigDecimal ownCanExtractWeight = BigDecimal.ZERO;
            BigDecimal platCanExtractWeight;
            if(ownOrderGoodsWeight.compareTo(BigDecimal.ZERO) == 0 ){
                //自有的车辆未发布货单,自有可提取吨数则为订单上自有可提取的吨数
                ownCanExtractWeight  =  orderInfo.getOwnCarryWeight();
                //平台可提取吨数 = 承运吨数 - 自有可提取吨数 - 平台已提取的吨数
                platCanExtractWeight = orderInfo.getTransportWeight().subtract(ownCanExtractWeight).
                        subtract(platOrderGoodsWeight);
            }else{
                //平台可提取吨数 = 承运吨数 - 自有已经提取吨数 - 平台已提取的吨数
                platCanExtractWeight = orderInfo.getTransportWeight().subtract(ownOrderGoodsWeight).
                        subtract(platOrderGoodsWeight);
            }

            return  OrderExtractWeightVO.builder().transportWeight(orderInfo.getTransportWeight())
                    .truckDemand(orderInfo.getTruckDemand())
                    .ownCarryWeight(orderInfo.getOwnCarryWeight())
                    .platformCarryWeight(orderInfo.getPlatformCarryWeight())
                    .ownCanExtractWeight(ownCanExtractWeight)
                    .platCanExtractWeight(platCanExtractWeight)
                    .canExtractWeight(platCanExtractWeight.add(ownCanExtractWeight))
                    .build();
        }else{
            log.warn("订单号：{} 的用车需求未知",orderNo);
            throw new ServiceSystemException(ResultEnum.DATA_ERROR,"未知的用车需求");
        }

    }

    @Override
    public BigDecimal getOrderResidueWeight(String orderNo) {
        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(orderNo).orElseThrow(
                PerformanceResultEnum.DATA_NOT_FIND);
        return orderInfo.getTransportWeight().subtract(getAlreadyWeight(orderInfo.getTransportWeight(),orderNo));
    }



    @Override
    public BigDecimal getAlreadyWeight(String orderNo) {
        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(orderNo).orElseThrow(
                PerformanceResultEnum.DATA_NOT_FIND);
        return getAlreadyWeight(orderInfo.getTransportWeight(),orderNo);
    }


    @Override
    public BigDecimal getAlreadyWeight(BigDecimal transportWeight, String orderNo) {
        BigDecimal alreadyWeight = BigDecimal.ZERO;    //该订单下已经拉运的重量

        List<OrderChild> orderChildList = orderChildDao.listByField(OrderChild::getOrderNo, orderNo);
        if(CollectionUtils.isEmpty(orderChildList)){
            return alreadyWeight;
        }

        for (OrderChild child : orderChildList) {
            if(child.getStatus() > OrderChildEnum.Status.COMPLETE.getCode()){
                continue;
            }
            if(Objects.nonNull(child.getLoadNet())){
                alreadyWeight = alreadyWeight.add(child.getLoadNet());
            }else{
                alreadyWeight = alreadyWeight.add(child.getWeight());
            }
        }
        return alreadyWeight;
    }


    //计算货单真实的提取量
    @Override
    public BigDecimal calcOrderGoodsRealExtractWeight(OrderGoods item){
        //取消，完成，完结的货单取 已拉运吨数 作为提取吨数，
        BigDecimal weight;
        if(Objects.equals(item.getOrderGoodsStatus(), OrderGoodsStatusEnum.Status.CANCEL.getCode())
                || Objects.equals(item.getOrderGoodsStatus(), OrderGoodsStatusEnum.Status.SUCCESS.getCode())
                || Objects.equals(item.getOrderGoodsStatus(), OrderGoodsStatusEnum.Status.COMPLETED.getCode())){
            weight = item.getAlreadyTransportWeight();
        }else{
            //货单的已拉运吨数大于提取吨数，使用已拉运吨数作为提取吨数
            if(item.getExtractWeight().compareTo
                    (Objects.nonNull(item.getAlreadyLoadWeight())?item.getAlreadyLoadWeight():BigDecimal.ZERO) >=0){
                weight = item.getExtractWeight();
            }else{
                weight = item.getAlreadyTransportWeight();
            }
        }

        return weight;
    }
}
