package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.CheckConditionDTO;
import com.prolog.rdc.tms.model.dto.ShipBillPriceDTO;
import com.prolog.rdc.tms.model.dto.SySParameterDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.StrategyBusinessMatchingDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.BmsShipBillDTO;
import com.prolog.rdc.tms.model.vo.basicConfigure.StrategyBusinessItemVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.StrategyBusinessMatchingVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.ShipCostStrategyService;
import com.prolog.rdc.tms.service.strategy.ExecuteStrategyServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ShipCostStrategyServiceImpl implements ShipCostStrategyService {

    @Autowired
    private ExecuteStrategyServiceImpl strategyService;
    @Autowired
    private LogisticsContractMapper logisticsContractMapper;
    @Autowired
    private FreightPriceMapper freightPriceMapper;
    @Autowired
    private BmsFreightPriceConditionMapper conditionMapper;
    @Autowired
    private ShipBillFeeTemporaryDetailMapper temporaryDetailMapper;
    @Autowired
    private ShipBillFeeDetailMapper shipBillFeeDetailMapper;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ShipBillPriceDTO> costStrategy(BmsShipBillDTO billDTO, String source) {

        List<BmsShipBillDetailModel> detailModels = billDTO.getDetailModelList();
        BmsShipBillHeaderModel costStrategy = billDTO.getModel();

        log.info("运单:" + JSON.toJSONString(costStrategy));
        log.info("运单明细:" + JSON.toJSONString(detailModels));

        // 1.承运商  2.司机
        String carrierCode = costStrategy.getCarriersCode();
        // 1.获取合同配置
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsLogisticsContractModel.class);
//        Restriction r1 = Restrictions.eq("cargoOwnerCode", costStrategy.getCargoOwnerCode());
        Restriction r2 = Restrictions.eq(BmsLogisticsContractModel::getSecondPartyCode, carrierCode);
        Restriction r3 = Restrictions.le("effectiveDate", costStrategy.getStartDate());
        Restriction r4 = Restrictions.ge("expiryDate", costStrategy.getStartDate());
        Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r16 = Restrictions.eq("status", 1);

        Restriction r27 = null;
        if (ObjectUtil.isNotEmpty(costStrategy.getCarrierType()) && costStrategy.getCarrierType().intValue() == 1) {
            r27 = Restrictions.eq(BmsLogisticsContractModel::getSecondPartyId, costStrategy.getCarrierId());
        } else if (ObjectUtil.isNotEmpty(costStrategy.getCarrierType()) && costStrategy.getCarrierType().intValue() == 2
                && ObjectUtil.isNotEmpty(costStrategy.getAffiliationId())) {
            r27 = Restrictions.eq(BmsLogisticsContractModel::getSecondPartyId, costStrategy.getAffiliationId());
        }
        criteria.setRestriction(Restrictions.and(r2, r3, r4, r5, r16, r27));
//        criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r16, r27));
        List<BmsLogisticsContractModel> models = logisticsContractMapper.findByCriteria(criteria);
        if (ObjectUtil.isEmpty(models)) {
            throw new PluginException("物流合同不存在，请先创建合同");
        }
        log.info("匹配到的合同:" + JSON.toJSONString(models));

        // 先删除所有的费用
        this.deleteFee(costStrategy, user, source);

        List<ShipBillPriceDTO> allList = Lists.newArrayList();

        Integer pricePcdMatchType = 4;
        StrategyBusinessMatchingDTO businessMatchingDTO = shipbillMatchBusinessRule(costStrategy, detailModels);
        if (ObjectUtil.isNotEmpty(businessMatchingDTO) && businessMatchingDTO.getPricePcdMatchTypeSelect().intValue() == 1) {
            pricePcdMatchType = businessMatchingDTO.getPricePcdMatchType();
        } else {
            // 获取价格表省市区匹配方式的系统参数
            RestMessage<SySParameterDTO> parameterModel = maindataTmsResource.queryParameter();
            if (ObjectUtil.isEmpty(parameterModel) || !parameterModel.isSuccess()) {
                throw new PluginException("获取系统参数异常");
            }
            pricePcdMatchType = parameterModel.getData().getPricePcdMatchType();
        }
        log.info("省市区匹配方式:" + pricePcdMatchType);
        // 获取所有合同的价格表
        List<String> contractNoList = models.stream().map(BmsLogisticsContractModel::getContractNo).collect(Collectors.toList());
        Criteria fCriteria = Criteria.forClass(BmsFreightPriceModel.class);
        Restriction r6 = Restrictions.in("contractNo", contractNoList.stream().toArray(String[]::new));
        Restriction r10 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r14 = Restrictions.eq("status", 1);
        fCriteria.setRestriction(Restrictions.and(r6, r10, r14));
        List<BmsFreightPriceModel> allPriceModelList = freightPriceMapper.findByCriteria(fCriteria);
        if (ObjectUtil.isEmpty(allPriceModelList)) {
            throw new PluginException(String.format("合同[%s]价格表不存在，请先创建价格表", contractNoList.stream().collect(Collectors.joining(","))));
        }
        log.info("获取所有合同的价格表:" + JSON.toJSONString(allPriceModelList));
        // 满足条件的价格表
        List<BmsFreightPriceModel> matchedCntPriceModelList = Lists.newArrayList();
        for (BmsFreightPriceModel priceModel : allPriceModelList) {
            // 3.查询匹配条件
            Criteria dCriteria = Criteria.forClass(BmsFreightPriceConditionModel.class);
            Restriction r8 = Restrictions.eq("priceNo", priceModel.getPriceNo());
            Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            dCriteria.setRestriction(Restrictions.and(r8, r9));
            List<BmsFreightPriceConditionModel> conditionList = conditionMapper.findByCriteria(dCriteria);
            if (ObjectUtil.isNotEmpty(conditionList)) {
                // 不是空，需要判断条件是否满足
                try {
                    CheckConditionDTO dto = this.checkCondition(conditionList, costStrategy, detailModels);
                    if (!dto.getFlag()) {
                        continue;
                    } else {
                        matchedCntPriceModelList.add(priceModel);
                    }
                } catch (Exception e) {
                    log.info("匹配价格表的满足条件失败" + e.getMessage());
                    throw new PluginException("匹配价格表的满足条件失败");
                }
            } else {
                matchedCntPriceModelList.add(priceModel);
            }
        }
        log.info("匹配到满足条件的价格表:" + JSON.toJSONString(matchedCntPriceModelList));
        // 用始发地，目的地匹配价格表
        List<BmsFreightPriceModel> matchedPcdPriceModelList = Lists.newArrayList();
        if (pricePcdMatchType.intValue() < BmsConstant.PRICE_PCD_MATCH_TYPE_IGNORE.intValue()) {
            switch (pricePcdMatchType.intValue()) {
                case 1:
                    matchedPcdPriceModelList = pcdPreciseMatchPrice(costStrategy, matchedCntPriceModelList);
                    break;
                case 2:
                    matchedPcdPriceModelList = pcdUpMatchPrice(costStrategy, matchedCntPriceModelList);
                    break;
                case 3:
                    matchedPcdPriceModelList = pcdUpIgnoreMatchPrice(costStrategy, matchedCntPriceModelList);
                    break;
            }
        } else {
            matchedPcdPriceModelList = matchedCntPriceModelList;
        }
        if (ObjectUtil.isEmpty(matchedPcdPriceModelList)) {
            throw new PrologException("没有匹配到价格表");
        }
        Map<String, List<BmsFreightPriceModel>> contractListMap = matchedPcdPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getContractNo));
        if (contractListMap.size() > 1) {
            throw new PrologException("运单匹配到多个合同:" + contractListMap.keySet().stream().collect(Collectors.joining(",")));
        }
        Map<String, List<BmsFreightPriceModel>> priceListMap = matchedPcdPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getExpenseName));
        if (priceListMap.size() != matchedPcdPriceModelList.size()) {
            throw new PrologException("运单匹配到重复的价格表");
        }
        String matchedPriceTblContractNo = matchedPcdPriceModelList.get(0).getContractNo();
        List<BmsLogisticsContractModel> contractModel = models.stream().filter(contract -> contract.getContractNo().equals(matchedPriceTblContractNo)).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(contractModel)) {
            throw new PluginException("价格表对应的合同不在合同数据中");
        }
        for (BmsFreightPriceModel priceModel : matchedPcdPriceModelList) {
            try {
                Integer settlementModel = priceModel.getSettlementModel();
                // 阶梯计费且计费单据是运单包裹
                if (settlementModel == 1 && priceModel.getSettlementOrderType() == 3) {
                    settlementModel = BmsConstant.LADDER_FOR_PACKAGE;
                } else if (settlementModel == 8 && priceModel.getSettlementOrderType() == 3) {
                    settlementModel = BmsConstant.JD_LADDER_COST;
                }
                // 1.获取运费
                List<ShipBillPriceDTO> list = strategyService.executeStrategy(contractModel.get(0), priceModel, settlementModel, costStrategy, source,user);
                allList.addAll(list);
            } catch (Exception e) {
                log.info("费用计算失败:" + e.getCause());
                throw new PrologException("费用计算失败");
            }
        }
        return allList;
    }

    private void deleteFee(BmsShipBillHeaderModel costStrategy, UserEntity user, String source) {
        // 0：试验，1：非试验
        if (source.equals("0")) {
            Criteria tcriteria = Criteria.forClass(BmsShipBillFeeTemporaryDetailModel.class);
            Restriction r9 = Restrictions.eq("shipbillNo", costStrategy.getShipbillNo());
            Restriction r10 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            tcriteria.setRestriction(Restrictions.and(r9, r10));
            List<BmsShipBillFeeTemporaryDetailModel> tmodels = temporaryDetailMapper.findByCriteria(tcriteria);
            if (ObjectUtil.isNotEmpty(tmodels)) {
                temporaryDetailMapper.deleteByCriteria(tcriteria);
            }
        } else {
            // 判断是否存 运单合同 + 价格表 + 来源
            Criteria criteria = Criteria.forClass(BmsShipBillFeeDetailModel.class);
            Restriction r2 = Restrictions.eq("billingSource", 1);
            Restriction r3 = Restrictions.eq("shipbillNo", costStrategy.getShipbillNo());
            Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            criteria.setRestriction(Restrictions.and(r2, r3, r4));
            List<BmsShipBillFeeDetailModel> models = shipBillFeeDetailMapper.findByCriteria(criteria);
            if (ObjectUtil.isNotEmpty(models)) {
                shipBillFeeDetailMapper.deleteByCriteria(criteria);
            }
        }
    }

    private CheckConditionDTO checkCondition(List<BmsFreightPriceConditionModel> conditionList, BmsShipBillHeaderModel costStrategy, List<BmsShipBillDetailModel> detailDTOS) throws Exception {
        log.info("价格表满足条件:" + JSON.toJSONString(conditionList));
        log.info("价格表满足条件匹配,运单:" + JSON.toJSONString(costStrategy));
        log.info("价格表满足条件匹配,运单明细:" + JSON.toJSONString(detailDTOS));
        Integer deliveryMethodType = costStrategy.getDeliveryMethodType();
        // 1客户 2仓库 3供应商
        Integer shipperType = costStrategy.getShipperType();
        Integer consigneeType = costStrategy.getConsigneeType();
        Integer orderType = costStrategy.getOrderType();
        Integer orderBusinessType = costStrategy.getOrderBusinessType();
        Integer transportType = costStrategy.getTransportType();
        Integer temperatureRequirement = costStrategy.getTemperatureRequirement();
        String cargoOwnerCode = costStrategy.getCargoOwnerCode();
        String shipperUnitCode = costStrategy.getShipperUnitCode();  // 发货放单位
        String consigneeUnitCode = costStrategy.getConsigneeUnitCode();  // 收货放单位
        String departmentCode = costStrategy.getSettlementDepartmentCode();
        String vehicleTypeCode = costStrategy.getVehicleTypeCode();
        CheckConditionDTO dto = new CheckConditionDTO();
        dto.setFlag(true);
        for (BmsFreightPriceConditionModel bmsFreightPriceConditionModel : conditionList) {
            log.info("价格表满足条件的明细条件:" + JSON.toJSONString(bmsFreightPriceConditionModel));
            // 条件 1：配送方式，2：发货方类型，3：收货放类型，4：订单类型，5：业务类型，6：运输模式，7：温度要求，8：货主，9：部门，10：商品,11:商品品类 12:车型
            Integer conditionType = bmsFreightPriceConditionModel.getConditionType();
            String conditionValue = bmsFreightPriceConditionModel.getConditionValue();
            String conditionValueName = bmsFreightPriceConditionModel.getConditionValueName();
            String unitCode = bmsFreightPriceConditionModel.getUnitCode();
            String unitName = bmsFreightPriceConditionModel.getUnitName();
            if (conditionType == 1 && !Objects.equals(deliveryMethodType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到配送方式对应的类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 2 && (!Objects.equals(shipperType.toString(), conditionValue) || !unitCode.contains(shipperUnitCode))) {
                dto.setMessage("没有匹配到发货方对应的类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 3 && (!Objects.equals(consigneeType.toString(), conditionValue) || !unitCode.contains(consigneeUnitCode))) {
                dto.setMessage("没有匹配到收货方类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 4 && !Objects.equals(orderType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到订单类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 5 && !Objects.equals(orderBusinessType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到业务类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 6 && !Objects.equals(transportType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到运输类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 7 && !Objects.equals(temperatureRequirement.toString(), conditionValue)) {
                dto.setMessage("没有匹配到温度类型");
                dto.setFlag(false);
                return dto;
            }
            // 货主
            if (conditionType == 8 && !unitCode.contains(cargoOwnerCode)) {
                dto.setMessage("没有匹配到货主");
                dto.setFlag(false);
                return dto;
            }
            // 部门
            if (conditionType == 9 && !unitCode.contains(departmentCode)) {
                dto.setMessage("没有匹配到部门");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 10) {
                List<String> itemNames = detailDTOS.stream().map(BmsShipBillDetailModel::getItemName).collect(Collectors.toList());
                for (String itemName : itemNames) {
                    if (unitName.contains(itemName)) {
                        dto.setFlag(true);
                        dto.setMessage(null);
                        return dto;
                    } else {
                        dto.setMessage("没有匹配到商品信息");
                        dto.setFlag(false);
                    }
                }
                if (!dto.getFlag()) {
                    return dto;
                }
            }
            if (conditionType == 11) {
                List<String> itemCategoryCode = detailDTOS.stream().map(BmsShipBillDetailModel::getItemCategoryCode).collect(Collectors.toList());
                for (String categoryCode : itemCategoryCode) {
                    if (unitCode.contains(categoryCode)) {
                        dto.setFlag(true);
                        dto.setMessage(null);
                        return dto;
                    } else {
                        dto.setMessage("没有匹配到商品品类信息");
                        dto.setFlag(false);
                    }
                }
                if (!dto.getFlag()) {
                    return dto;
                }
            }
            if (conditionType == 12 && !unitCode.contains(vehicleTypeCode)) {
                dto.setMessage("没有匹配到车型");
                dto.setFlag(false);
                return dto;
            }
        }
        return dto;
    }

    /**
     * 运单匹配业务规则
     *
     * @param model
     * @return
     */
    public StrategyBusinessMatchingDTO shipbillMatchBusinessRule(BmsShipBillHeaderModel model, List<BmsShipBillDetailModel> detailModels) {
        // 新增后自动提交判定
        StrategyBusinessMatchingVO matchBusinessVO = new StrategyBusinessMatchingVO();
        // 配送方式
        matchBusinessVO.setDeliveryMethodType(model.getDeliveryMethodType());
        // 发货方类型
        matchBusinessVO.setShipperType(model.getShipperType());
        // 发货方单位ID
        matchBusinessVO.setShipperUnitId(model.getShipperUnitId());
        // 收货方类型
        matchBusinessVO.setConsigneeType(model.getConsigneeType());
        // 收货方单位ID
        matchBusinessVO.setConsigneeUnitId(model.getConsigneeUnitId());
        // 订单类型
        matchBusinessVO.setOrderType(model.getOrderType());
        // 订单业务类型
        matchBusinessVO.setOrderBusinessType(model.getOrderBusinessType());
        // 运输模式
        matchBusinessVO.setTransportType(model.getTransportType());
        // 温度要求
        matchBusinessVO.setTemperatureRequirement(model.getTemperatureRequirement());
        // 货主ID
        matchBusinessVO.setCargoOwnerId(model.getCargoOwnerId());
        // 部门
        matchBusinessVO.setDepartmentId(model.getDepartmentId());
        matchBusinessVO.setTotalPcs(model.getTotalPcs());
        matchBusinessVO.setTotalWeight(model.getTotalWeight());

        if (ObjectUtil.isNotEmpty(detailModels)) {
            List<StrategyBusinessItemVO> businessItemVOS = Lists.newArrayList();
            for (BmsShipBillDetailModel detailModel : detailModels) {
                StrategyBusinessItemVO businessItemVO = new StrategyBusinessItemVO();
                businessItemVO.setItemId(detailModel.getItemId());
                businessItemVO.setItemCategoryId(detailModel.getItemCategoryId());
                businessItemVO.setPcs(detailModel.getPcs());
                businessItemVO.setWeight(detailModel.getWeight());

                businessItemVOS.add(businessItemVO);
            }
            matchBusinessVO.setBusinessItemVOS(businessItemVOS);
        }
        log.info("运单匹配业务规则入参:" + JSON.toJSONString(matchBusinessVO));
        RestMessage<List<StrategyBusinessMatchingDTO>> matchRs = maindataTmsResource.matchingBusinessExecute(matchBusinessVO);
        if (!matchRs.isSuccess()) {
            throw new PrologException("运单【" + model.getShipbillNo() + "】调用maindata服务运单匹配业务规则失败");
        }
        List<StrategyBusinessMatchingDTO> strategyBusinessMatchingDTOS = matchRs.getData();
        log.info("运单匹配到的业务规则:" + JSON.toJSONString(strategyBusinessMatchingDTOS));
        if (ObjectUtil.isEmpty(strategyBusinessMatchingDTOS)) {
            return null;
        }
        if (strategyBusinessMatchingDTOS.size() > 1) {
            throw new PrologException("运单【" + model.getShipbillNo() + "】匹配到多个业务规则策略");
        }
        return strategyBusinessMatchingDTOS.get(0);
    }

    /**
     * 省市区精准匹配
     *
     * @param model
     * @return
     */
    public List<BmsFreightPriceModel> pcdPreciseMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> matchedPriceTbl = Lists.newArrayList();

        // 匹配始发地
        if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity()) &&
                ObjectUtil.isNotEmpty(model.getShipperDistrict())) {
            // 省市区匹配
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && model.getShipperDistrict().equals(price.getShipperDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity())) {
            // 省市匹配
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince())) {
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && ObjectUtil.isEmpty(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> ObjectUtil.isEmpty(price.getShipperProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(matchedPriceTbl)) {
            return null;
        }
        // 匹配目的地
        if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeDistrict())) {
            // 省市区匹配
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && model.getConsigneeDistrict().equals(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity())) {
            // 省市匹配
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince())) {
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && ObjectUtil.isEmpty(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> ObjectUtil.isEmpty(price.getConsigneeProvince())).collect(Collectors.toList());
        }
        return matchedPriceTbl;
    }

    /**
     * 省市区向上匹配
     *
     * @param model
     * @return
     */
    public List<BmsFreightPriceModel> pcdUpMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> shipperMatchedPriceTbl = Lists.newArrayList();
        // 匹配始发地
        if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity()) &&
                ObjectUtil.isNotEmpty(model.getShipperDistrict())) {
            // 省市区匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && model.getShipperDistrict().equals(price.getShipperDistrict())).collect(Collectors.toList());
            // 省市匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && model.getShipperCity().equals(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && model.getShipperCity().equals(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
            // 省匹配
            if (ObjectUtil.isNotEmpty(shipperMatchedPriceTbl)) {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity())) {
            // 省市匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
            // 省匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince())) {
            shipperMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && ObjectUtil.isEmpty(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            shipperMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> ObjectUtil.isEmpty(price.getShipperProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(shipperMatchedPriceTbl)) {
            return null;
        }
        // 匹配目的地
        List<BmsFreightPriceModel> consigneeMatchedPriceTbl = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeDistrict())) {
            // 省市区匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && model.getConsigneeDistrict().equals(price.getConsigneeDistrict())).collect(Collectors.toList());
            // 省市匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                List<String> expenseName = consigneeMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && model.getConsigneeCity().equals(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && model.getConsigneeCity().equals(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
            // 省匹配
            if (ObjectUtil.isNotEmpty(consigneeMatchedPriceTbl)) {
                List<String> expenseName = consigneeMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity())) {
            // 省市匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
            // 省匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                List<String> expenseName = tmpMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = null;
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince())) {
            consigneeMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && ObjectUtil.isEmpty(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            consigneeMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> ObjectUtil.isEmpty(price.getConsigneeProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(consigneeMatchedPriceTbl)) {
            return null;
        }
        return consigneeMatchedPriceTbl;
    }

    public List<BmsFreightPriceModel> pcdUpIgnoreMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> pcdUpMatchPrice = pcdUpMatchPrice(model, matchedCntPriceModelList);
        if (ObjectUtil.isNotEmpty(pcdUpMatchPrice)) {
            return pcdUpMatchPrice;
        } else {
            return matchedCntPriceModelList;
        }
    }
}