package cn.freemud.demo.service.impl;

import cn.freemud.adapter.ActivityAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.constant.CustomerScoreConstant;
import cn.freemud.constant.ShoppingCartConstant;
import cn.freemud.demo.entities.bo.promotion.GetActivityBO;
import cn.freemud.demo.constant.ResponseConstant;
import cn.freemud.demo.entities.bo.goods.ShoppingCartGoodsBO;
import cn.freemud.demo.entities.bo.goods.*;
import cn.freemud.demo.entities.bo.member.*;
import cn.freemud.demo.entities.bo.product.GetRequiredProductListBO;
import cn.freemud.demo.entities.bo.promotion.ActivityBO;
import cn.freemud.demo.manager.coupon.CouponManager;
import cn.freemud.demo.manager.customer.CustomerManager;
import cn.freemud.demo.manager.product.ProductManager;
import cn.freemud.demo.manager.promotion.PromotionManager;
import cn.freemud.demo.service.GetShoppingCartGoodsApportionService;
import cn.freemud.entities.dto.ActivityCalculationDiscountRequestDto;
import cn.freemud.entities.dto.ActivityCalculationDiscountResponseDto;
import cn.freemud.entities.dto.CheckSpqInfoResponseDto;
import cn.freemud.entities.dto.activity.ActivityDiscountsDto;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
import cn.freemud.entities.dto.calculate.CalculationSharingDiscountResponseDto;
import cn.freemud.entities.dto.shoppingCart.SendPoint;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.ItemService;
import cn.freemud.service.impl.AssortmentSdkService;
import cn.freemud.service.impl.calculate.CalculationCommonService;
import cn.freemud.utils.LogUtil;
import cn.freemud.utils.WebUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.application.sdk.api.productcenter.domain.ProductBeanDTO;
import com.freemud.sdk.api.assortment.shoppingcart.constant.CommonsConstant;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import com.freemud.sdk.api.assortment.shoppingcart.service.ShoppingCartBaseService;
import com.freemud.sdk.api.assortment.shoppingcart.service.impl.ShoppingCartBaseServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.freemud.constant.ApplicationConstant.*;
import static java.util.stream.Collectors.toList;

@Service
public class AbstractApportionService implements GetShoppingCartGoodsApportionService {

    @Autowired
    private CustomerManager customerManager;

    @Autowired
    private ProductManager productManager;

    @Autowired
    private AssortmentSdkService assortmentSdkService;

    @Autowired
    private ShoppingCartBaseServiceImpl shoppingCartBaseService;

    @Autowired
    private ShoppingBaseServiceImpl shoppingBaseService;

    @Autowired
    private PromotionManager promotionManager;

    @Autowired
    private CalculationCommonService calculationCommonService;

    @Autowired
    private ActivityAdapter activityAdapter;

    @Autowired
    private RedisCache redisCache;

    private static final String limitCartKey = "ecology:kgd:wxappconfig:open_platform_partner_wxapp_config:appkey_";

    @Autowired
    private ItemService itemService;


    /**
     * 加车的流程
     *
     * @return
     */
    public final ShoppingCartApportionBO getApportion(ShoppingCartGoodsApportionBO apportionBO) {
        // 基本参数校验
        this.checkParams(apportionBO);

        // 获取购物车和加车商品信息
        CheckBussinessRulesBO checkBussinessRulesBO = this.getShoppingCartInfo(apportionBO);

        // 业务校验,例如商品数量库存之类的信息
        AddGoodsToShoppingCartBO addGoodsToShoppingCartBO = this.checkBusinessRules(apportionBO, checkBussinessRulesBO);

        // 添加商品到购物车
        DiscountResultBO discountResultBO = this.addGoodsToShoppingCart(apportionBO, addGoodsToShoppingCartBO);

        // 去促销计算优惠
        CalCostBO calCostBO = this.getDiscountResult(apportionBO, discountResultBO);

        // 计算促销不计算的费用,例如配送费
        DistributeBO distributeBO = this.calCost(apportionBO, calCostBO);

        // 拼装购物车价格
        ShoppingCartApportionBO shoppingCartApportionBO = this.equally(apportionBO, distributeBO);

        return shoppingCartApportionBO;
    }

    /**
     * 计算不在促销计算范围里的费用
     * @param addGoodsBO
     * @return
     */
    public final DistributeBO calCost(ShoppingCartGoodsApportionBO addGoodsBO, CalCostBO calCostBO) {
        DistributeBO commonSetMessageBO = this.calCommCost(addGoodsBO, calCostBO);

        DistributeBO customSetMessageBO = this.calCustomCost(addGoodsBO, calCostBO, commonSetMessageBO);

        return customSetMessageBO;
    }

    @Override
    public CalCostBO getDiscountResultBefore(ShoppingCartGoodsApportionBO baseRequestDTO, DiscountResultBO discountResultBO) {
        // 计算配送费
        CalCostBO calCostBO = new CalCostBO();
        return calCostBO;
    }

    public final CalCostBO getDiscountResult(ShoppingCartGoodsApportionBO addGoodsBO, DiscountResultBO discountResultBO) {
        CalCostBO before = this.getDiscountResultBefore(addGoodsBO, discountResultBO);

        CalCostBO commonSetMessageBO = this.getComDiscountResult(addGoodsBO, discountResultBO, before);

        CalCostBO customSetMessageBO = this.getDiscountResultAfter(addGoodsBO, discountResultBO, commonSetMessageBO);

        return customSetMessageBO;
    }

    public final ShoppingCartApportionBO equally(ShoppingCartGoodsApportionBO addGoodsBO, DistributeBO distributeBO) {
        ShoppingCartApportionBO commonSetMessageBO = this.commDistribute(addGoodsBO, distributeBO);

        ShoppingCartApportionBO customSetMessageBO = this.customDistribute(addGoodsBO, distributeBO, commonSetMessageBO);

        return customSetMessageBO;
    }

    /**
     * 设置提示语
     * @param addGoodsBO
     * @return
     */
    public final ShoppingCartApportionBO setMessage(ShoppingCartGoodsApportionBO addGoodsBO, ApportionSetMessageBO setMessageBO) {
        ShoppingCartApportionBO commonAddGoodsShoppingCartBO = this.setCommMessage(addGoodsBO, setMessageBO);

        ShoppingCartApportionBO customAddGoodsShoppingCartBO = this.setCustomMessage(addGoodsBO, setMessageBO, commonAddGoodsShoppingCartBO);

        return customAddGoodsShoppingCartBO;
    }


    /**
     * 请求基本参数校验
     * @return
     */
    public final BaseResponse checkParams(ShoppingCartGoodsApportionBO baseRequestDTO) {
        BaseResponse commonBaseResponse = this.checkCommParams(baseRequestDTO);
        if (!ResponseConstant.RESPONSE_SUCCESS_STR.equals(commonBaseResponse.getCode())){
            return commonBaseResponse;
        }
        BaseResponse customBaseResponse = this.checkCustomParams(baseRequestDTO);
        if (!ResponseConstant.RESPONSE_SUCCESS_STR.equals(customBaseResponse.getCode())){
            return customBaseResponse;
        }
        return ResponseBuilder.success();
    }

    /**
     * 1. 获取加车的商品信息
     * 2. 获取购物车的商品信息
     *
     * @return
     */
    public final CheckBussinessRulesBO getShoppingCartInfo(ShoppingCartGoodsApportionBO baseRequestBO) {
        CheckBussinessRulesBO bo = new CheckBussinessRulesBO();
        // 获取用户信息
        CustomerInfo userInfo = customerManager.getUserInfo(baseRequestBO.getSessionId(), baseRequestBO.getManagerService().getCustomerService());
        bo.setUserId(userInfo.getUserId());
        bo.setIsMember(userInfo.getIsMember());
        baseRequestBO.setUserId(userInfo.getUserId());

        // 获取购物车信息
        // 注意，围餐和点餐redis数据结构不一样
        List<CartGoods> allCartGoodsList = assortmentSdkService.getShoppingCart(baseRequestBO.getPartnerId(), baseRequestBO.getShopId(), userInfo.getUserId(), baseRequestBO.getSessionId(), null, shoppingCartBaseService);
        if (CollectionUtils.isEmpty(allCartGoodsList)) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_GETINFO_INVAILD);
        }
        bo.setCartGoods(allCartGoodsList);

        // 加价购
        List<ShoppingCartGoodsApportionBO.SendGoods> sendGoodsList = baseRequestBO.getSendGoods();
        ShoppingCartGoodsApportionBO.PremiumExchangeActivity premiumExchangeActivity = baseRequestBO.getPremiumExchangeActivity();
        if (CollectionUtils.isNotEmpty(sendGoodsList)) {
            processSendGoods(sendGoodsList, baseRequestBO.getPartnerId(), baseRequestBO.getShopId() , baseRequestBO.getMenuType() , shoppingCartBaseService);
        } else {
            //组装加价购商品
            if (null != premiumExchangeActivity && CollectionUtils.isNotEmpty(premiumExchangeActivity.getProducts())) {
                List<ShoppingCartGoodsApportionBO.SendGoods> sendGoods = premiumExchangeActivity.getProducts().stream().map(product -> {
                    ShoppingCartGoodsApportionBO.SendGoods sendGood = new ShoppingCartGoodsApportionBO.SendGoods();
                    sendGood.setGoodsId(product.getSkuId());
                    sendGood.setQty(product.getQty());
                    sendGood.setOriginalPrice(product.getOriginalPrice());
                    sendGood.setActivityCode(premiumExchangeActivity.getActivityCode());
                    return sendGood;
                }).collect(toList());
                baseRequestBO.setSendGoods(sendGoods);
            }
        }


        return bo;
    }


    /**
     * 具体业务逻辑校验, 例如商品数量,库存等校验
     *
     * @return
     */
    public final AddGoodsToShoppingCartBO checkBusinessRules(ShoppingCartGoodsApportionBO baseRequestDTO, CheckBussinessRulesBO checkBussinessRulesBO) {
        AddGoodsToShoppingCartBO commAddGoodsToShoppingCartBO = this.checkCommBusinessRules(baseRequestDTO, checkBussinessRulesBO);
        AddGoodsToShoppingCartBO customAddGoodsToShoppingCartBO = this.checkCustomBusinessRules(baseRequestDTO, checkBussinessRulesBO, commAddGoodsToShoppingCartBO);
        return customAddGoodsToShoppingCartBO;
    }


    /**
     * 添加商品到购物车,并重新设置购物车
     *
     * @return
     */
    public final DiscountResultBO addGoodsToShoppingCart(ShoppingCartGoodsApportionBO baseRequestDTO, AddGoodsToShoppingCartBO addGoodsToShoppingCartBO) {

        DiscountResultBO commCalCostBO = this.commAddGoodsToShoppingCart(baseRequestDTO, addGoodsToShoppingCartBO);

        DiscountResultBO customCalCostBO = this.customAddGoodsToShoppingCart(baseRequestDTO, addGoodsToShoppingCartBO, commCalCostBO);

        return customCalCostBO;
    }


    private BaseResponse checkCommParams(ShoppingCartGoodsApportionBO baseRequestDTO) {

        // 用户选择的商品、数量不在促销返回的优惠信息中，返回错误
        if(baseRequestDTO == null ){
            throw new ServiceException(ResponseResult.SHOPPING_CART_REQUEST_NOT_EMPTY);
        }


        if (StringUtils.isEmpty(baseRequestDTO.getShopId())){
            throw new ServiceException(ResponseResult.SHOPPING_CART_SHOP_ID_NOT_EMPTY);
        }

        return ResponseBuilder.success();
    }

    private AddGoodsToShoppingCartBO checkCommBusinessRules(ShoppingCartGoodsApportionBO baseRequestDTO, CheckBussinessRulesBO checkBussinessRulesBO) {
        AddGoodsToShoppingCartBO bo = new AddGoodsToShoppingCartBO();


        List<CartGoods> cartGoodsList = checkBussinessRulesBO.getCartGoods();


        /**
         *  校验该名店是否有必选商品
         *  1. 调用商品服务拿到该门店是否有必选商品
         *  2. 如果有，则和购物车的商品对比
         */
        GetRequiredProductListBO getRequiredProductListBO = new GetRequiredProductListBO();
        getRequiredProductListBO.setMenuType(BusinessTypeEnum.getByType(baseRequestDTO.getMenuType()).getCode());
        getRequiredProductListBO.setPartnerId(baseRequestDTO.getPartnerId());
        getRequiredProductListBO.setShopId(baseRequestDTO.getShopId());

        List<String> requiredProductList = productManager.getRequiredProductList(getRequiredProductListBO, baseRequestDTO.getManagerService().getProductService());
        if (CollectionUtils.isNotEmpty(requiredProductList)){
            List<String> spuIds = cartGoodsList.stream().map(good -> good.getSpuId()).collect(Collectors.toList());
            // 两个集合只要没有交集，就返回true
            if (org.springframework.util.CollectionUtils.isEmpty(requiredProductList.stream().filter(item -> spuIds.contains(item)).collect(Collectors.toList()))) {
                throw new ServiceException(ResponseResult.SHOPPING_CART_REQUIRED_PRODUCT_NOT_EXIST);
            }
        }


        // 检查校验购物车商品(是否合法,上下架,点餐方式,是否在当前菜单中...),并移除非法商品
        ShoppingCartContext cartContext = convert2ShopingCartContext(baseRequestDTO);
        CheckCartRequest checkCartRequest = shoppingBaseService.checkShoppingCart(cartGoodsList, null, cartContext);

        com.freemud.sdk.api.assortment.shoppingcart.domain.ShoppingCartGoodsResponseVo cartGoodsResponseVo = checkCartRequest.getShoppingCartGoodsResponseVo();


        //商品不再售卖状态或价格变动，直接返回报错
        if (cartGoodsResponseVo != null) {
            if (cartGoodsResponseVo.getCartGoodsStates() != null && cartGoodsResponseVo.getCartGoodsStates().isHasInvalidGoods()) {
                throw new ServiceException(ResponseResult.STORE_ITEM_CHECK_INVAILD);
            }
            if (cartGoodsResponseVo.getCartGoodsStates() != null && cartGoodsResponseVo.getCartGoodsStates().isPriceChanged()) {
                throw new ServiceException(ResponseResult.SHOPPING_CART_ACTIVITY_CHANGE);
            }
        }


        checkBussinessRulesBO.setChanged(checkCartRequest.getChanged());
        checkBussinessRulesBO.setToastMsg(checkCartRequest.getToastMsg());

        bo.setCartGoods(JSONArray.parseArray(JSONObject.toJSONString(checkCartRequest.getCartGoodsList()), CartGoods.class));
        bo.setChanged(checkCartRequest.getChanged());
        bo.setProduct(checkBussinessRulesBO.getProduct());
        bo.setShoppingCartContext(cartContext);
        bo.setToastMsg(checkCartRequest.getToastMsg());
        bo.setIsMember(checkBussinessRulesBO.getIsMember());

        return bo;
    }

    private DiscountResultBO commAddGoodsToShoppingCart(ShoppingCartGoodsApportionBO baseRequestDTO, AddGoodsToShoppingCartBO addGoodsToShoppingCartBO) {
        DiscountResultBO calCostBO = new DiscountResultBO();
        ShoppingCartContext cartContext = addGoodsToShoppingCartBO.getShoppingCartContext();

        assortmentSdkService.setShoppingCart(cartContext.getPartnerId(), cartContext.getShopId(), cartContext.getUserId(),
                addGoodsToShoppingCartBO.getCartGoods(), baseRequestDTO.getSessionId(), "", shoppingCartBaseService);

        calCostBO.setCartGoods(addGoodsToShoppingCartBO.getCartGoods());
        calCostBO.setChanged(addGoodsToShoppingCartBO.getChanged());
        calCostBO.setShoppingCartContext(addGoodsToShoppingCartBO.getShoppingCartContext());
        calCostBO.setToastMsg(addGoodsToShoppingCartBO.getToastMsg());
        calCostBO.setValidCouponMap(addGoodsToShoppingCartBO.getValidCouponMap());
        calCostBO.setIsMember(addGoodsToShoppingCartBO.getIsMember());
        return calCostBO;
    }

    public final void updateShoppingCartCache(DiscountResultBO calCostBO) {
        return ;
    }

    private DistributeBO calCommCost(ShoppingCartGoodsApportionBO baseRequestDTO, CalCostBO calCostBO) {
        DistributeBO distributeBO = new  DistributeBO();
        distributeBO.setCalculationDiscountBO(calCostBO.getCalculationDiscountBO());
        distributeBO.setCartGoods(calCostBO.getCartGoods());
        distributeBO.setChanged(calCostBO.getChanged());
        distributeBO.setToastMsg(calCostBO.getToastMsg());
        distributeBO.setDeliveryAmount(calCostBO.getDeliveryAmount());
        return distributeBO;
    }

    private ShoppingCartApportionBO setCommMessage(ShoppingCartGoodsApportionBO baseRequestDTO, ApportionSetMessageBO setMessageBO) {

        ShoppingCartApportionBO shoppingCartGoodsBO = setMessageBO.getShoppingCartGoodsBO();

        return shoppingCartGoodsBO;
    }

    private CalCostBO getComDiscountResult(ShoppingCartGoodsApportionBO baseRequestDTO, DiscountResultBO discountResultBO, CalCostBO before) {
        if (before.getGetCalculationDiscountBO() == null){
            before.setCalculationDiscountBO(new CalculationDiscountBO());
            return before;
        }
        CalculationDiscountBO calculationDiscountBO = promotionManager.calculationDiscount(before.getGetCalculationDiscountBO(), baseRequestDTO.getManagerService().getPromotionService());
        calculationDiscountBO.getResult().setValidCouponMap(before.getValidCouponMap());
        before.setCalculationDiscountBO(calculationDiscountBO);

        return before;
    }

    private ShoppingCartApportionBO commDistribute(ShoppingCartGoodsApportionBO baseRequestDTO, DistributeBO distributeBO) {

        ActivityQueryDto activityQueryDto = activityAdapter.getActivityQueryDto(baseRequestDTO.getPartnerId(), baseRequestDTO.getShopId(),
                baseRequestDTO.getUserId(), baseRequestDTO.getAppId(), baseRequestDTO.getOrderType());

        ShoppingCartApportionBO shoppingCartGoodsBO = new ShoppingCartApportionBO();

        /**
         * 用促销价格初始化购物车行记录成交价
         */
        ShoppingGoodsAmountBO shoppingGoodsAmountBO = this.initShoppingCart(distributeBO.getCalculationDiscountBO(), distributeBO.getCartGoods());

        CalculationDiscountBO.CalculationDiscountResult discountResult = null;
        if (distributeBO.getCalculationDiscountBO() != null){
            discountResult = distributeBO.getCalculationDiscountBO().getResult();
        }

        /**
         * 组建大的优惠信息
         */
        List<ActivityDiscountsDto> activityDiscountsDtos = this.setShoppingCartGoodsDtoActivityDiscounts(discountResult);
        shoppingCartGoodsBO.setActivityDiscountsDtos(activityDiscountsDtos);



        /**
         * 活动库存
         * 过滤出加价购
         */

        if (null != discountResult) {
            List<CalculationDiscountBO.CalculationDiscountResult.Discount> addMoneyDiscounts = discountResult.getDiscounts()
                    .stream()
                    .filter(discount -> ActivityTypeEnum.TYPE_81.getCode().equals(discount.getType()))
                    .collect(Collectors.toList());
            List<SubtractStockVO> stocks = filterSendGoodsStocks(discountResult.getStocks(), baseRequestDTO, addMoneyDiscounts);
            if (CollectionUtils.isNotEmpty(stocks)) shoppingCartGoodsBO.setStocks(stocks);
        }
        List<CalculationDiscountBO.CalculationDiscountResult.Goods> goods = null;
        if (discountResult !=null) {
            goods = discountResult.getGoods();
        }



        /**
         * 利用促销赋值totalDiscountAmount
         */
        List<CartGoods> cartGoodsList = distributeBO.getCartGoods();
        List<ShoppingCartApportionBO.CartGoodsDetailDto> cartGoodsDetailDtoList = CollectionUtils.isEmpty(shoppingCartGoodsBO.getProducts()) ? new ArrayList<>() : shoppingCartGoodsBO.getProducts();
        CalculationDiscountBO.CalculationDiscountResult.Goods find = null;
        for (CartGoods product : cartGoodsList) {
            //循环购物车商品券
            if (product.getCartGoodsUid().startsWith(CommonsConstant.COUPON_PREFIX)) {
                String spqId = product.getCartGoodsUid().substring(CommonsConstant.COUPON_PREFIX.length());
                // 计算优惠信息时，已将券校验过，放在map中
                Map<String, CheckSpqInfoResponseDto> validCouponMap = discountResult == null ? new HashMap<>() : discountResult.getValidCouponMap();
                if (MapUtils.isNotEmpty(validCouponMap)) {
                    CheckSpqInfoResponseDto checkSpqInfoResponseDto = validCouponMap.get(spqId);
                    if (checkSpqInfoResponseDto != null) {
                        product.setOriginalPrice(checkSpqInfoResponseDto.getPrice());
                        product.setSpuId(checkSpqInfoResponseDto.getSpuId());
                        product.setSkuId(StringUtils.isEmpty(checkSpqInfoResponseDto.getSkuId()) ? checkSpqInfoResponseDto.getSpuId() : checkSpqInfoResponseDto.getSkuId());
                        product.setQty(1);
                        product.setCouponCode(checkSpqInfoResponseDto.getCouponCode());
                        product.setSpuName(checkSpqInfoResponseDto.getSpuName());
                        product.setSpecProductId(checkSpqInfoResponseDto.getDefaultSpecId());
                        product.setSubName(checkSpqInfoResponseDto.getDefaultSpecName());
                        product.setExtra(checkSpqInfoResponseDto.getExtras());
                        if (GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType().equals(product.getGoodsType())) {
                            CalculationDiscountBO.CalculationDiscountResult.Goods discountGoods = discountResult.getGoods()
                                    .stream()
                                    .filter(d -> product.getCartGoodsUid().equals(d.getCartGoodsUid()))
                                    .findFirst()
                                    .orElse(null);
                            if (discountGoods != null) {
                                product.setAmount(discountGoods.getRealAmount());
                            } else {
                                product.setAmount(checkSpqInfoResponseDto.getPrice());
                            }
                        }
                        product.setOriginalAmount(checkSpqInfoResponseDto.getPrice());
                    }
                }
            }

            if (goods!=null) {
                find = goods.stream().filter((k) -> k.getCartGoodsUid().equals(product.getCartGoodsUid())).findFirst().get();
            }
            ShoppingCartApportionBO.CartGoodsDetailDto cartGoodsDetailDto = calculationCommonService.convertCartGoods2NewDetailGoodsList(find, product, baseRequestDTO.getPartnerId());
            cartGoodsDetailDtoList.add(cartGoodsDetailDto);
        }

        // 买赠
        List<ShoppingCartApportionBO.CartGoodsDetailDto> giftGoods = this.buyGift(distributeBO.getCalculationDiscountBO().getResult(), distributeBO.getCartGoods(), activityQueryDto, baseRequestDTO);

        /**
         * 加价购
         */
        ApportionAdditionBO additionBO = this.additionResponse(distributeBO.getCalculationDiscountBO().getResult(), baseRequestDTO);


        /**
         * 积分抵扣
         */
        ScoreReduceBO scoreReduceBO = this.scoreReduce(distributeBO.getCalculationDiscountBO().getResult(), baseRequestDTO, shoppingGoodsAmountBO);

        // 购买会员卡
        BuyMemberCardBO buyMemberCardBO = this.addNeedCardAmount(baseRequestDTO);


        /**
         * 配送费
         */
        DeliveryBO delivery = null;
        if (BusinessTypeEnum.SAAS_DELIVERY.getCode().equals(baseRequestDTO.getMenuType())) {
            delivery = this.delivery(distributeBO.getCalculationDiscountBO(), baseRequestDTO,
                    activityQueryDto, distributeBO.getDeliveryAmount());
        }

        /**
         * 包装费
         */
        Long packAmount = this.getPackAmount(baseRequestDTO, shoppingGoodsAmountBO);

        if (discountResult!=null ) {
            List<Integer> activityTypes = discountResult.getDiscounts().stream().map(CalculationDiscountBO.CalculationDiscountResult.Discount::getType).collect(Collectors.toList());
            if (activityTypes.contains(221)) {
                CalculationDiscountBO.CalculationDiscountResult.Discount discountDTO = discountResult.getDiscounts().stream().filter(d -> 221 == d.getType()).findFirst().get();
                SendPoint sendPoint = convert2SendPoint(discountDTO);
                shoppingCartGoodsBO.setSendPoint(sendPoint);
            }

        }

        shoppingCartGoodsBO.setOriginalTotalAmount(shoppingGoodsAmountBO.getOriginalTotalAmount());
        Long totalAmount = shoppingGoodsAmountBO.getTotalAmount();
        Long totalDiscountAmount = shoppingGoodsAmountBO.getTotalDiscountAmount();
        Long originalTotalAmount = shoppingGoodsAmountBO.getOriginalTotalAmount();

        // 加价购金额
        if (additionBO != null){
            originalTotalAmount += additionBO.getOriginalTotalAmount();
            cartGoodsDetailDtoList.addAll(additionBO.getAddCartGoodsDetailList());
        }
        // 买赠
        if (CollectionUtils.isNotEmpty(giftGoods)){
            cartGoodsDetailDtoList.addAll(giftGoods);
        }
        // 积分抵扣
        if(scoreReduceBO != null){
            shoppingCartGoodsBO.setScoreReduceAmount(scoreReduceBO.getReduceAmount() == null ? 0 : scoreReduceBO.getReduceAmount().longValue());
            shoppingCartGoodsBO.setReduceScore(scoreReduceBO.getUseScore() == null ? 0 : scoreReduceBO.getUseScore().longValue());
            totalDiscountAmount += scoreReduceBO.getDiscountAmount();
            totalAmount -= scoreReduceBO.getDiscountAmount();
        }

        // 购买会员卡
        if (buyMemberCardBO != null){
            Integer activityPrice = buyMemberCardBO.getActivityPrice();
            Integer firstCouponAmount = buyMemberCardBO.getFirstCouponAmount();
            Integer needCardAmount = activityPrice - firstCouponAmount;
            shoppingCartGoodsBO.setMemberCardAmount(needCardAmount);
            shoppingCartGoodsBO.setCardOriginalAmount(activityPrice);
            shoppingCartGoodsBO.setCardDiscountAmount(firstCouponAmount);
            originalTotalAmount += activityPrice;
            totalAmount += needCardAmount;
            totalDiscountAmount += firstCouponAmount;
        }

        // 配送费
        if (delivery != null){
            shoppingCartGoodsBO.setDiscountDeliveryActivityCode(delivery.getActivityCode());
            shoppingCartGoodsBO.setDeliveryAmount(delivery.getDeliveryAmount());
            shoppingCartGoodsBO.setDiscountDeliveryAmount(delivery.getDiscountDeliveryAmount());
            shoppingCartGoodsBO.setThresholdAmount(delivery.getThresholdAmount());
            shoppingCartGoodsBO.setIsDiscountDelivery(delivery.getIsDiscountDelivery());
        }
        shoppingCartGoodsBO.setProducts(cartGoodsDetailDtoList);
        shoppingCartGoodsBO.setPackageAmount(packAmount);
        shoppingCartGoodsBO.setTotalAmount(totalAmount);
        shoppingCartGoodsBO.setTotalDiscountAmount(totalDiscountAmount);
        shoppingCartGoodsBO.setOriginalTotalAmount(originalTotalAmount);

        return shoppingCartGoodsBO;
    }

    private SendPoint convert2SendPoint(CalculationDiscountBO.CalculationDiscountResult.Discount discountDTO) {
        SendPoint sendPointNew = new SendPoint();

        CalculationDiscountBO.CalculationDiscountResult.SendPointDto sendPointVo = discountDTO.getSendPointVo();
        if (sendPointVo != null) {
            sendPointNew.setMaxNum(sendPointVo.getMaxNum());
            sendPointNew.setSendPoint(sendPointVo.getSendPoint());
            sendPointNew.setValidityDateDays(sendPointVo.getValidityDateDays());
            sendPointNew.setActivityCode(discountDTO.getActivityCode());
            sendPointNew.setEndTime(discountDTO.getEndTime());
            sendPointNew.setStoreLevel(sendPointVo.getStoreLevel());
            sendPointNew.setIsContinueExchange(sendPointVo.getIsContinueExchange());
            return sendPointNew;
        }
        return null;
    }

    /**
     * 库存扣减加价购商品 要过滤掉没有换购的商品
     *
     * @param stocks                    扣减库存
     * @param baseRequestDTO 购物车请求信息
     * @param addMoneyDiscounts         加价购活动
     * @return 返回应该扣减的加价购商品库存
     */
    private List<SubtractStockVO> filterSendGoodsStocks(List<SubtractStockVO> stocks
            , ShoppingCartGoodsApportionBO baseRequestDTO
            , List<CalculationDiscountBO.CalculationDiscountResult.Discount> addMoneyDiscounts) {
        if (CollectionUtils.isEmpty(stocks) || CollectionUtils.isEmpty(addMoneyDiscounts)) {
            return stocks;
        }
        List<SubtractStockVO> subtractStockVOs = stocks.stream().filter(subtractStockVO -> ActivityTypeEnum.TYPE_81.getCode().equals(subtractStockVO.getActivityType())).collect(Collectors.toList());
        List<SubtractStockVO.SubtractStockGoodsVO> goodsStock = null;
        if (CollectionUtils.isNotEmpty(subtractStockVOs)) {
            SubtractStockVO subtractStockVO = subtractStockVOs.get(0);
            goodsStock = subtractStockVO.getGoodsStock();
        }
        if (null == goodsStock) {
            return stocks;
        }
        Map<String, SubtractStockVO.SubtractStockGoodsVO> mapSubstractStocks = new HashMap<>();
        if (CollectionUtils.isNotEmpty(goodsStock)) {
            mapSubstractStocks = goodsStock.stream().collect(Collectors.toMap(SubtractStockVO.SubtractStockGoodsVO::getGoodsId, Function.identity(), (k1, k2) -> k1));
        }
        //获取加价购商品
        List<ShoppingCartGoodsApportionBO.SendGoods> sendGoods = baseRequestDTO.getSendGoods();
        if (CollectionUtils.isNotEmpty(sendGoods)) {
            List<String> needSendGoodsId = sendGoods.stream().map(ShoppingCartGoodsApportionBO.SendGoods::getGoodsId).collect(Collectors.toList());
            goodsStock.clear();
            for (String goodId : needSendGoodsId) {
                SubtractStockVO.SubtractStockGoodsVO subtractStockGoodsVO = mapSubstractStocks.get(goodId);
                if (null != mapSubstractStocks.get(goodId)) {
                    goodsStock.add(subtractStockGoodsVO);
                }
            }
        } else {
            return stocks.stream().filter(subtractStockVO -> !ActivityTypeEnum.TYPE_81.getCode().equals(subtractStockVO.getActivityType())).collect(Collectors.toList());
        }
        return stocks;
    }

    /**
     * 设置购物车整体享受的活动集合
     *
     * @param discountResult
     */
    public List<ActivityDiscountsDto> setShoppingCartGoodsDtoActivityDiscounts(CalculationDiscountBO.CalculationDiscountResult discountResult) {


        List<ActivityDiscountsDto> activityDiscountsDtos = new ArrayList<>();
        if (discountResult == null) return activityDiscountsDtos;
        Integer type = 2;
        List<ActivityTypeEnum> activityTypeEnums = new LinkedList<>();
        activityTypeEnums.add(ActivityTypeEnum.TYPE_11);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_12);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_3);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_31);
        List<Integer> typeEnums = activityTypeEnums.stream().map(ActivityTypeEnum::getCode).collect(Collectors.toList());
        for (CalculationDiscountBO.CalculationDiscountResult.Goods good : discountResult.getGoods()) {
            if (CollectionUtils.isNotEmpty(good.getSmallMaterial())) {
                List<CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> sm = good.getSmallMaterial()
                        .stream()
                        .filter(d -> type.equals(d.getType())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(sm)) continue;
                for (CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial s : sm) {
                    if (CollectionUtils.isEmpty(s.getDiscounts())) continue;
                    HashMap<Integer, Long> discountMap = new HashMap<>();
                    for (CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount d : s.getDiscounts()) {
                        if (!typeEnums.contains(d.getType())) continue;
                        Integer sType = d.getType();
                        discountMap.put(sType, d.getDiscount());
                    }

                    if (discountMap.isEmpty()) continue;
                    if (CollectionUtils.isEmpty(good.getDiscounts())) continue;
                    for (CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount discount : good.getDiscounts()) {
                        Integer mType = discount.getType();
                        if (discountMap.get(mType) != null) {
                            discount.setDiscount(discount.getDiscount() + discountMap.get(mType).longValue());
                        }
                    }
                }
            }
        }
        List<CalculationDiscountBO.CalculationDiscountResult.Discount> discounts = discountResult.getDiscounts();
        for (CalculationDiscountBO.CalculationDiscountResult.Discount discount : discounts) {
            int discountAmount = (discount.getDiscount() == null) ? 0 : discount.getDiscount();
            Integer discountType = discount.getType();
            if (discountType != null && discountAmount >= 0) {
                ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
                activityDiscountsDto.setActivityCode(discount.getActivityCode());
                activityDiscountsDto.setActivityName(discount.getActivityName());
                activityDiscountsDto.setActivityType(calculationCommonService.convertType(discountType));
                activityDiscountsDto.setDiscountAmount(0 - discountAmount);
                activityDiscountsDtos.add(activityDiscountsDto);
            }
        }
        return activityDiscountsDtos;
    }


    /**
     * 在原价、现价、折扣价上增加第一次使用会员卡的费用
     *
     */
    public BuyMemberCardBO addNeedCardAmount(ShoppingCartGoodsApportionBO baseRequestDTO) {
        BuyMemberCardBO buyMemberCardBO = new BuyMemberCardBO();
        ShoppingCartGoodsApportionBO.BuyMemberCard buyMemberCard = baseRequestDTO.getBuyMemberCard();
        if (baseRequestDTO.getBuyMemberCard() == null || StringUtils.isEmpty(buyMemberCard.getPaidId()) || StringUtils.isEmpty(buyMemberCard.getRuleId())) {
            return null;
        }
        GetPaidRuleRequestBO getPaidRuleRequestDto = new GetPaidRuleRequestBO();
        getPaidRuleRequestDto.setPartnerId(baseRequestDTO.getPartnerId());
        getPaidRuleRequestDto.setPaidId(buyMemberCard.getPaidId());
        getPaidRuleRequestDto.setRuleId(buyMemberCard.getRuleId());
        PaidRuleResponseBO paidRule = customerManager.getPaidRule(getPaidRuleRequestDto, baseRequestDTO.getManagerService().getCustomerService());
        if (paidRule == null){
            return null;
        }
        // 购买会员卡的金额
        Integer activityPrice = paidRule.getActivityPrice();

        Integer firstCouponAmount = paidRule.getFirstCouponAmount() == null ? 0 : paidRule.getFirstCouponAmount();
        Integer needCardAmount = activityPrice - firstCouponAmount;

        buyMemberCardBO.setActivityPrice(activityPrice);
        buyMemberCardBO.setFirstCouponAmount(firstCouponAmount);

        return buyMemberCardBO;
    }

    public Long getPackAmount(ShoppingCartGoodsApportionBO baseRequestDTO, ShoppingGoodsAmountBO shoppingGoodsAmountBO) {
        //==========================  购物车查询特有逻辑  =================================
        // 到店自取包装费设为null,外卖要计算包装费，flag为1表示去结算
        // 兼容老版本判断null
        if (Objects.equals(baseRequestDTO.getOrderType(), CreateOrderType.COLLECT_GOODS.getCode())
                && (Objects.equals(baseRequestDTO.getReachStoreType(), null)
                || Objects.equals(baseRequestDTO.getReachStoreType(), OrderType.EAT_IN.getCode()))) {
            return null;
        } else if ((Objects.equals(baseRequestDTO.getOrderType(), CreateOrderType.TAKE_OUT.getCode())
                || Objects.equals(baseRequestDTO.getReachStoreType(), OrderType.COLLECT_GOODS.getCode()))
                && Objects.equals(baseRequestDTO.getFlag(), CouponFlag.YES.getCode())) {
            return  shoppingGoodsAmountBO.getNewPackAmount() == null ? 0L : shoppingGoodsAmountBO.getNewPackAmount();
        }
        return null;
    }

    public DeliveryBO delivery(CalculationDiscountBO calculationDiscountBO, ShoppingCartGoodsApportionBO baseRequestDTO
            , ActivityQueryDto activityQueryDto, Long calDeliveryAmount
            ) {
        CalculationDiscountBO.CalculationDiscountResult discountResult = null;
        Long deliveryAmount = 0L;
        if (calDeliveryAmount != null){
            deliveryAmount = calDeliveryAmount;
        }
        if (calculationDiscountBO != null){
            discountResult = calculationDiscountBO.getResult();
        }

        DeliveryBO deliveryBO = new DeliveryBO();
        DecimalFormat df = new DecimalFormat("###.##");
        List<ActivityTypeEnum> activityTypeEnums = new LinkedList<>();
        activityTypeEnums.add(ActivityTypeEnum.TYPE_14);

        GetActivityBO getActivityBO = new GetActivityBO();
        getActivityBO.setActivityQueryDto(activityQueryDto);
        getActivityBO.setActivityTypeEnums(activityTypeEnums);
        ActivityBO activityBO = promotionManager.queryActivityByType(getActivityBO, baseRequestDTO.getManagerService().getPromotionService());
        BenefitBeanBO beanDto = new BenefitBeanBO();
        if (activityBO != null){
            beanDto = activityBO.getBenefits().get(0);
            deliveryBO.setActivityCode(activityBO.getActivityCode());
        }
        CalculationDiscountBO.CalculationDiscountResult.Discount discount=null;
        if (discountResult != null && CollectionUtils.isNotEmpty(discountResult.getDiscounts())) {
            discount = discountResult.getDiscounts().stream().filter((d) -> ActivityTypeEnum.TYPE_14.getCode().equals(d.getType())).findFirst().orElse(null);
        }

        if(discount!=null) {
            if(beanDto.getBenefitType() == 1) {
                String desc = DELIVERY_DISCOUNT_DESC2;
                deliveryBO.setDeliveryDiscountDesc(String.format(desc, df.format(beanDto.getThresholdAmount().doubleValue() /100) ));
            }
            else {
                String desc = DELIVERY_DISCOUNT_DESC1;
                deliveryBO.setDeliveryDiscountDesc(String.format(desc, df.format(beanDto.getThresholdAmount().doubleValue() /100) ,df.format(beanDto.getDiscountAmount().doubleValue() / 100)));
            }
            deliveryBO.setDeliveryAmount(deliveryAmount);
            deliveryBO.setDiscountDeliveryAmount(discountResult.getDistributionFee());
            deliveryBO.setThresholdAmount(discount.getThresholdAmount());
            deliveryBO.setIsDiscountDelivery(true);
        } else {
            if (activityBO!=null) {
                if(beanDto.getBenefitType() == 1) {
                    String desc = DELIVERY_DISCOUNT_DESC2;
                    deliveryBO.setDeliveryDiscountDesc(String.format(desc, df.format(beanDto.getThresholdAmount().doubleValue() /100) ));
                }
                else {
                    String desc = DELIVERY_DISCOUNT_DESC1;
                    deliveryBO.setDeliveryDiscountDesc(String.format(desc, df.format(beanDto.getThresholdAmount().doubleValue() /100 ),df.format(beanDto.getDiscountAmount().doubleValue() / 100)));
                }

                deliveryBO.setDeliveryAmount(deliveryAmount);
                deliveryBO.setDiscountDeliveryAmount(deliveryAmount);
                deliveryBO.setIsDiscountDelivery(false);

            } else {
                String desc = DELIVERY_DISCOUNT_DESC3;
                deliveryBO.setDeliveryDiscountDesc(String.format(desc, df.format(deliveryAmount.doubleValue() / 100)));
                deliveryBO.setDeliveryAmount(deliveryAmount);
                deliveryBO.setDiscountDeliveryAmount(deliveryAmount);
                deliveryBO.setIsDiscountDelivery(false);
            }
        }
        return deliveryBO;
    }


    public ScoreReduceBO scoreReduce(CalculationDiscountBO.CalculationDiscountResult discountResult
            , ShoppingCartGoodsApportionBO baseRequestDTO, ShoppingGoodsAmountBO shoppingGoodsAmountBO) {
        ScoreReduceBO scoreReduce = new ScoreReduceBO();
        if (baseRequestDTO == null || baseRequestDTO.getUseCustomerScore() == null
                || baseRequestDTO.getUseCustomerScore() == null
                || baseRequestDTO.getUseCustomerScore().equals(CustomerScoreConstant.NO_DISPLAY.getValue())) {
            return null;
        }

        GetUserScoreUseDetailBO request = new GetUserScoreUseDetailBO();
        request.setMemberId(baseRequestDTO.getUserId());
        request.setPaidAmount(getValue(shoppingGoodsAmountBO.getTotalAmount()));
        request.setPartnerId(baseRequestDTO.getPartnerId());
        UserScoreUserDetailBO userScoreUseDetail = null;
        try {
            // 加入try catch是为了custom服务挂掉，购物车服务可以也可以正常
            userScoreUseDetail = customerManager.getUserScoreUseDetail(request, baseRequestDTO.getManagerService().getCustomerService());
        } catch (Exception ex) {
            ErrorLog.printErrorLog("getUserScoreUseDetailError", "/user/scoreUseDetail", request, ex);
        }

        if (userScoreUseDetail != null) {
            Integer discountAmount = 0;
            if (CustomerScoreConstant.SUBSTRACT.getValue().equals(baseRequestDTO.getUseCustomerScore())) {
                //设置 购物车总金额=购物车总价-积分扣减金额
                discountAmount = getValue(userScoreUseDetail.getReduceAmount());
            }
            //设置 积分抵扣VO
            scoreReduce.setCurrentScore(getValue(userScoreUseDetail.getCurrentScore()));
            scoreReduce.setReduceAmount(getValue(userScoreUseDetail.getReduceAmount()));
            scoreReduce.setReducePriceLimit(getValue(userScoreUseDetail.getReducePriceLimit()));
            scoreReduce.setOverlayOffers(userScoreUseDetail.getOverlayOffers());
            scoreReduce.setScoreReduceState(getValue(userScoreUseDetail.getScoreState()));
            // 是否可优惠同享{0所有订单均可抵扣,1仅限原价订单才可抵扣（享受了促销活动、或使用了优惠券，不能进行积分抵扣
            if (getValue(userScoreUseDetail.getOverlayOffers()) == 0) {
                scoreReduce.setScoreReduceState(getValue(userScoreUseDetail.getScoreState()));
            } else {
                if (StringUtils.isNotBlank(baseRequestDTO.getCouponCode()) || (discountResult != null && discountResult.getTotalDiscountAmount().intValue() > 0)
                        || (discountResult != null && !CollectionUtils.isEmpty(discountResult.getDiscounts()))) {
                    //是否有换购
                    int type81 = 0;
                    for (CalculationDiscountBO.CalculationDiscountResult.Discount discount : discountResult.getDiscounts()) {
                        if (ActivityTypeEnum.TYPE_81.getCode().equals(discount.getType())) {
                            type81 = 1;
                            break;
                        }
                    }
                    //集点
                    long discountCount = discountResult.getDiscounts().stream().filter(discount -> !ActivityTypeEnum.TYPE_221.getCode().equals(discount.getType())).count();

                    //积分抵扣开关禁用 有换购活动 且选中了换购商品
                    // - 有换购且选中了换购商品
                    // - 有换购且没有选中换购商品 且除集点以外还有其他促销
                    if ((type81 == 0 && discountCount >= 1)
                            || (type81 == 1 && !CollectionUtils.isEmpty(baseRequestDTO.getSendGoods()))
                            || (type81 == 1 && discountCount > 1)) {
                        scoreReduce.setScoreReduceState(5);
                        userScoreUseDetail.setScoreState(5);
                        scoreReduce.setReduceAmount(0);
                    }
                }
            }
            scoreReduce.setUseScore(getValue(userScoreUseDetail.getUseScore()));
            scoreReduce.setScoreState(userScoreUseDetail.getScoreState());
            scoreReduce.setScoreReduceRate(userScoreUseDetail.getScoreReduceRate());
            scoreReduce.setDiscountAmount(discountAmount);
        } else {
            scoreReduce = null;
        }
        return scoreReduce;
    }

    private Integer getValue(Object object) {
        Integer result = 0;
        try {
            if (object != null) {
                if (object instanceof Integer) {
                    result = (Integer) object;
                }
                else if (object instanceof String) {
                    result = Integer.parseInt((String) object);
                }
                else if (object instanceof Double) {
                    result = (int) ((double) object);
                }
                else if (object instanceof Float) {
                    result = (int) ((float) object);
                }
                else if (object instanceof BigDecimal) {
                    result = ((BigDecimal) object).intValue();
                }
                else if (object instanceof Long) {
                    result = ((Long) object).intValue();
                }
            }
        } catch (Exception ex) {
            LogUtil.error("getScoreValueFail", "", "", ex);
        }
        return result;
    }

    public ApportionAdditionBO additionResponse(CalculationDiscountBO.CalculationDiscountResult discountResult
            , ShoppingCartGoodsApportionBO baseRequestDTO) {
        ApportionAdditionBO additionBO = new ApportionAdditionBO();

        List<ShoppingCartApportionBO.CartGoodsDetailDto> addCartGoodsDetailList = new ArrayList<>();
        ShoppingCartGoodsApportionBO.PremiumExchangeActivity premiumExchangeActivity = baseRequestDTO.getPremiumExchangeActivity();
        if (discountResult == null || CollectionUtils.isEmpty(discountResult.getGoods()) || premiumExchangeActivity == null || CollectionUtils.isEmpty(premiumExchangeActivity.getProducts())) {
            return null;
        }
        List<CalculationDiscountBO.CalculationDiscountResult.Goods> manyHgs = discountResult.getGoods()
                .stream()
                .filter(d -> CalculationGoodsType.TYPE_2.getType().equals(d.getCartGoodType()))
                .collect(Collectors.toList());


        if (CollectionUtils.isEmpty(manyHgs)) {
            throw new ServiceException(ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST);
        }

        //添加商品行
        List<String> productIds = premiumExchangeActivity.getProducts().stream().map(p -> StringUtils.isEmpty(p.getSkuId()) ? p.getSpuId() : p.getSkuId()).collect(Collectors.toList());
        Map<String, GetProductsVo> getProductsVoMap = itemService.getProducts(productIds, baseRequestDTO.getPartnerId(), baseRequestDTO.getShopId(), BusinessTypeEnum.getByType(baseRequestDTO.getMenuType()).getCode());
        if (getProductsVoMap.isEmpty()) {
            throw new ServiceException(ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST);
        }
        // 获取计算返回的价格
        Long originalTotalAmount = 0L;
        //Long totalAmount = shoppingCartGoodsDto.getTotalAmount();
        //Long totalDiscountAmount = shoppingCartGoodsDto.getTotalDiscountAmount();
        //加价换购活动总优惠
        for (CreateOrderVo.PremiumExchangeActivity.Product product : premiumExchangeActivity.getProducts()) {

            String goodsId = StringUtils.isEmpty(product.getSkuId()) ? product.getSpuId() : product.getSkuId();
            GetProductsVo getProductsVo = getProductsVoMap.get(goodsId);
            if (null == getProductsVo) {
                continue;
            }
            CalculationDiscountBO.CalculationDiscountResult.Goods hgGood = manyHgs.stream().filter(d -> goodsId.equals(d.getGoodsId())).findFirst().orElse(null);
            if (hgGood == null) {
                continue;
            }
            ShoppingCartApportionBO.CartGoodsDetailDto cartGoodsDetailDto = this.getCartGoodsDetailDto(product, getProductsVo, goodsId, hgGood);
            addCartGoodsDetailList.add(cartGoodsDetailDto);
            //2.计算优惠价格
            originalTotalAmount += getProductsVo.getFinalPrice();
            //totalDiscountAmount += cartGoodsDetailDto.getTotalDiscountAmount();
            //currenttotalDiscountAmount += cartGoodsDetailDto.getTotalDiscountAmount();
            // 3.设置商品行优惠明细
            CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount sendActivity = hgGood.getDiscounts().get(0);
            ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
            activityDiscountsDto.setActivityCode(sendActivity.getActivityCode());
            activityDiscountsDto.setActivityName(sendActivity.getActivityName());
            activityDiscountsDto.setActivityType(ActivityTypeEnum.TYPE_81.getCode());
            activityDiscountsDto.setDiscountAmount(cartGoodsDetailDto.getTotalDiscountAmount());
            List<ActivityDiscountsDto> activityDiscountsDtoList = new ArrayList<>();
            activityDiscountsDtoList.add(activityDiscountsDto);
            cartGoodsDetailDto.setActivityDiscountsDtos(activityDiscountsDtoList);
        }

        additionBO.setOriginalTotalAmount(originalTotalAmount);
        additionBO.setAddCartGoodsDetailList(addCartGoodsDetailList);
        return additionBO;
    }


    public ShoppingCartApportionBO.CartGoodsDetailDto getCartGoodsDetailDto(CreateOrderVo.PremiumExchangeActivity.Product product
            , GetProductsVo getProductsVo
            , String goodsId
            , CalculationDiscountBO.CalculationDiscountResult.Goods hgGood) {

        ShoppingCartApportionBO.CartGoodsDetailDto cartGoodsDetailDto = new ShoppingCartApportionBO.CartGoodsDetailDto();
        cartGoodsDetailDto.setOriginalPrice(hgGood.getOriginalPrice());
        cartGoodsDetailDto.setTotalDiscountAmount(hgGood.getDiscountAmount().intValue());
        cartGoodsDetailDto.setSpuId(product.getSpuId());
        cartGoodsDetailDto.setSkuId(goodsId);
        cartGoodsDetailDto.setQty(product.getQty());
        cartGoodsDetailDto.setSpuName(getProductsVo != null ? getProductsVo.getSpuName() : "");
        cartGoodsDetailDto.setSkuName(product.getSkuName());
        cartGoodsDetailDto.setPicture(getProductsVo != null ? getProductsVo.getSpuPicture() : "");
        cartGoodsDetailDto.setActivityType(ActivityTypeEnum.TYPE_81.getCode());
        cartGoodsDetailDto.setClassificationId(getProductsVo.getCategory());
        cartGoodsDetailDto.setClassificationName(getProductsVo.getCategoryName());
        List<ShoppingCartApportionBO.CartGoodsDetailDto.CartGoodsExtra> cartGoodsExtraList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(product.getAttributes())) {
            for (CreateOrderVo.PremiumExchangeActivity.Product.Attribute attribute : product.getAttributes()) {
                ShoppingCartApportionBO.CartGoodsDetailDto.CartGoodsExtra cartGoodsExtra = new ShoppingCartApportionBO.CartGoodsDetailDto.CartGoodsExtra();
                cartGoodsExtra.setAttributeId(attribute.getAttributeId());
                cartGoodsExtra.setAttributeName(attribute.getAttributeValue());
                cartGoodsExtraList.add(cartGoodsExtra);
            }
        }
        cartGoodsDetailDto.setExtraList(cartGoodsExtraList);
        return cartGoodsDetailDto;
    }

    /**
     * 构建加价购商品校验参数
     *
     * @param baseRequestDTO 入参
     * @return 返回商品
     */
    public List<CreateOrderVo.PremiumExchangeActivity.Product> buildPremiumExchangeActivityProduct(ShoppingCartGoodsApportionBO baseRequestDTO) {

        List<ShoppingCartGoodsApportionBO.SendGoods> sendGoods = baseRequestDTO.getSendGoods();
        List<String> goodsIds = sendGoods
                .stream()
                .map(ShoppingCartGoodsApportionBO.SendGoods::getGoodsId)
                .collect(Collectors.toList());

        Map<String, ShoppingCartGoodsApportionBO.SendGoods> goodQtyMap = sendGoods
                .stream()
                .collect(Collectors.toMap(ShoppingCartGoodsApportionBO.SendGoods::getGoodsId, Function.identity(), (k1, k2) -> k1));
        GetProductBO getProductBO = new GetProductBO();
        getProductBO.setMenuType(baseRequestDTO.getMenuType());
        getProductBO.setPartnerId(baseRequestDTO.getPartnerId());
        getProductBO.setStoreId(baseRequestDTO.getShopId());
        getProductBO.setGoodsId(goodsIds);

        List<ProductBO> productsInfo = productManager.getProductsInfo(getProductBO, baseRequestDTO.getManagerService().getProductService());

        if (CollectionUtils.isEmpty(productsInfo)) {
            throw new ServiceException(ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST);
        }

        return productsInfo.stream().map(productBean ->{
            CreateOrderVo.PremiumExchangeActivity.Product product = new CreateOrderVo.PremiumExchangeActivity.Product();
            List<ProductBO.SkuProductBean> skuList = productBean.getSkuList();
            List<String> skuIds = null;
            if (null!=skuList) {
                skuIds = skuList.stream().map(ProductBO.SkuProductBean::getSkuId).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(skuIds)) {
                for (String skuId : skuIds) {
                    ShoppingCartGoodsApportionBO.SendGoods sendGood = goodQtyMap.get(skuId);
                    if (null != sendGood) {
                        product.setQty(sendGood.getQty());
                        product.setSpuId(productBean.getSpuId());
                        product.setSkuId(sendGood.getGoodsId());
                        product.setStatus(productBean.getStatus());
                        break;
                    }
                }
            }
            else {
                ShoppingCartGoodsApportionBO.SendGoods sendGood = goodQtyMap.get(productBean.getSpuId());
                if (null != sendGood) {
                    product.setQty(sendGood.getQty());
                    product.setSpuId(sendGood.getGoodsId());
                    product.setSkuId(sendGood.getGoodsId());
                    product.setStatus(productBean.getStatus());
                }
            }
            return product;
        }).collect(Collectors.toList());
    }


    /**
     * check加价购
     *
     * @param additionalProducts     购物车添加的加价购商品
     * @param additionalActivityList 加价购活动
     * @return
     */
    private ResponseResult checkAdditionalGoods(List<CreateOrderVo.PremiumExchangeActivity.Product> additionalProducts
            , List<CalculationDiscountBO.CalculationDiscountResult.SendActivity> additionalActivityList) {
        //无加价购活动
        if (CollectionUtils.isEmpty(additionalActivityList)) {
            return ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST;
        }
        //加价购活动中换购商品为空
        List<CalculationDiscountBO.CalculationDiscountResult.SendActivity> additionalActivity = additionalActivityList
                .stream()
                .filter(activity -> ObjectUtils.equals(ActivityTypeEnum.TYPE_81.getCode(), activity.getActivityType()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(additionalActivity)) {
            return ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST;
        }
        //购物车中总加价购数量>每单可换购总数量
        Integer totalAdditionalProductCount = additionalProducts.stream().mapToInt(CreateOrderVo.PremiumExchangeActivity.Product::getQty).sum();
        if (totalAdditionalProductCount > additionalActivity.get(0).getMaxNum()) {
            return ResponseResult.PREMIUM_EXCHANGE_GOODS_OUT_OF_LIMIT;
        }
        //加价购活动中的换购商品列表Map
        Map<String, CalculationDiscountBO.CalculationDiscountResult.SendActivity.SendGoods> sendGoodsMap = additionalActivity.get(0).getSendGoods()
                .stream()
                .collect(Collectors.toMap(CalculationDiscountBO.CalculationDiscountResult.SendActivity.SendGoods::getGoodsId, Function.identity(), (k1, k2) -> k1));
        for (CreateOrderVo.PremiumExchangeActivity.Product product : additionalProducts) {
            if (ShoppingCartConstant.OFF_LINE_PRODUCT.equals(product.getStatus()) || ShoppingCartConstant.SOLD_OUT_PRODUCT.equals(product.getStatus())) {
                return ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST;
            }
            if (ShoppingCartConstant.NOT_ON_LINE_PRODUCT.equals(product.getStatus())) {
                return ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_ON_LINE;
            }
            // 购物车中加价购商品不在活动商品列表中 或  每个商品的换购数量>活动限制数量
            CalculationDiscountBO.CalculationDiscountResult.SendActivity.SendGoods sendGoods = Objects.isNull(sendGoodsMap.get(product.getSkuId())) ? sendGoodsMap.get(product.getSpuId()) : sendGoodsMap.get(product.getSkuId());
            if (Objects.isNull(sendGoods)) {
                return ResponseResult.PREMIUM_EXCHANGE_ACTIVITY_NOT_EXIST;
            }
            if (product.getQty() > sendGoods.getSendNumber()) {
                return ResponseResult.PREMIUM_EXCHANGE_GOODS_OUT_OF_LIMIT;
            }
        }
        return ResponseResult.SUCCESS;
    }



    private List<ChooseGoodsBO> bugGiftAndSendCup(CalculationDiscountBO.CalculationDiscountResult result, List<CartGoods> cartGoods, ActivityQueryDto activityQueryDto, ShoppingCartGoodsApportionBO baseRequestDTO){

        if(result == null){
            return null;
        }

        //  过略出来买一赠一寄杯活动，没有直接返回
        List<CalculationDiscountBO.CalculationDiscountResult.Discount> discounts = result.getDiscounts();
        if(null == discounts || discounts.isEmpty()){
            return null;
        }
        List<CalculationDiscountBO.CalculationDiscountResult.Discount> buyOneGiveOneSendDiscounts = discounts
                .stream()
                .filter(discount -> ObjectUtils.equals(discount.getType(), ActivityTypeEnum.TYPE_63.getCode()))
                .collect(Collectors.toList());
        if(null == buyOneGiveOneSendDiscounts || buyOneGiveOneSendDiscounts.isEmpty()){
            return null;
        }

        if (buyOneGiveOneSendDiscounts == null || CollectionUtils.isEmpty(result.getGoods())) {
            return null;
        }
/*        String menuType = shoppingCartInfoRequestVo == null ? null : shoppingCartInfoRequestVo.getMenuType();
        // 构建赠品detail
        List<ProductBeanDTO> beanDTOList = this.drawGiftInfo(discountResult, activityQueryDto, menuType);
        this.setCartGoods(discountResult, cartGoodsList, beanDTOList);*/

        // 设置用户可以选择的寄送商品券码
        return this.buildSendGoods(result);

    }


    private void setToastMsgIfNotExist(ShoppingCartGoodsBO shoppingCartGoodsBO, String message) {
        if (StringUtils.isEmpty(shoppingCartGoodsBO.getToastMsg())) {
            shoppingCartGoodsBO.setToastMsg(message);
        }
    }

    /**
     * 设置没有加入购物车的提示语
     * @param messageBuilder
     */
    private ArrayList<ActivityList> setMessageNotInShoppingCart(StringBuilder messageBuilder, ActivityBO activityBO, List<BenefitBeanBO> benefitBeanBOList, BenefitBeanBO benefitBeanBO) {

        ArrayList<ActivityList> activityList = new ArrayList<>();
        if (Objects.equals(ActivityTypeEnum.TYPE_11.getCode(), activityBO.getActivityType())) {
            messageBuilder.append("每满 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(benefitBeanBO.getThresholdAmount() * 1.00 / 100))
                    .append("</span> 减 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(benefitBeanBO.getDiscountAmount() * 1.00 / 100))
                    .append("</span> ")
                    .append("最高减 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(activityBO.getMaxMoney() * 1.00 / 100))
                    .append("</span> 元");

            //满足  x 元 减 Y 元 ，最高 减 Z元
            ActivityList notInShopping = new ActivityList();
            notInShopping.setTipType(1);
            notInShopping.setSatisfy(WebUtil.formatAmount(benefitBeanBO.getThresholdAmount() * 1.00 / 100).toString());
            notInShopping.setDeduct(WebUtil.formatAmount(benefitBeanBO.getDiscountAmount() * 1.00 / 100).toString());
            notInShopping.setMaxDeduct(WebUtil.formatAmount(activityBO.getMaxMoney() * 1.00 / 100).toString());
            activityList.add(notInShopping);
        }
        if (Objects.equals(ActivityTypeEnum.TYPE_12.getCode(), activityBO.getActivityType())) {
            int len = benefitBeanBOList.size();
            // // 购物车中无商品或者存在与满减互斥的活动
            for (int i = len - 1; i >= 0; i--) {
                benefitBeanBO = benefitBeanBOList.get(i);
                messageBuilder.append("满 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(benefitBeanBO.getThresholdAmount() * 1.00 / 100))
                        .append("</span> 减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(benefitBeanBO.getDiscountAmount() * 1.00 / 100))
                        .append("</span> 元");
                if (i > 0) messageBuilder.append("，");
            }
            //  阶梯满减：满足 X 元 减 Y 元,
            for (int j = len - 1; j >= 0; j--) {
                benefitBeanBO = benefitBeanBOList.get(j);
                ActivityList notInShopping = new ActivityList();
                notInShopping.setTipType(2);
                notInShopping.setSatisfy(WebUtil.formatAmount(benefitBeanBO.getThresholdAmount() * 1.00 / 100).toString());
                notInShopping.setDeduct(WebUtil.formatAmount(benefitBeanBO.getDiscountAmount() * 1.00 / 100).toString());
                activityList.add(notInShopping);
            }
        }
        return activityList;
    }


    /**
     * 设置加入商品满足购物车时的提示语
     *
     * @param messageBuilder
     * @param activityPrompts
     * @param activityResponseDto
     */
    private List<ActivityList> setMessageSatisfyCart(StringBuilder messageBuilder, List<CalculationDiscountBO.CalculationDiscountResult.ActivityPrompt> activityPrompts
            , ActivityBO activityResponseDto) {
        ArrayList<ActivityList> result = new ArrayList<>();
        ActivityList satisfyList = new ActivityList();
        CalculationDiscountBO.CalculationDiscountResult.ActivityPrompt activityPrompt = activityPrompts.get(0);
        if (activityPrompt.getAlreadyDiscountAmount() == null
                || activityPrompt.getAlreadyDiscountAmount() == 0) {
            messageBuilder.append("满 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(activityPrompt.getThresholdAmount() * 1.00 / 100))
                    .append("</span> 减 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100))
                    .append("</span> ")
                    .append("还差 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100))
                    .append("</span> 元");
            // 满足 X 元 减 Y 元 还差 Z元
            satisfyList.setTipType(3);
            satisfyList.setSatisfy(WebUtil.formatAmount(activityPrompt.getThresholdAmount() * 1.00 / 100).toString());
            satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100).toString());
            satisfyList.setMissing(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100).toString());
        } else {
            Long toDiscountAmout;
            if (Objects.equals(ActivityTypeEnum.TYPE_11.getCode(), activityResponseDto.getActivityType())) {
                toDiscountAmout = activityPrompt.getDiscountAmout() + activityPrompt.getAlreadyDiscountAmount();
            } else {
                toDiscountAmout = activityPrompt.getDiscountAmout();
            }
            //已减 X 元 再买 Y 元 减 Z 元
            messageBuilder.append("已减 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100))
                    .append("</span> 元 再买 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100))
                    .append("</span> 元减 <span style=\"color:#fa5555\">")
                    .append(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100))
                    .append("</span> 元");
            satisfyList.setTipType(4);
            satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100).toString());
            satisfyList.setAgainBuy(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100).toString());
            satisfyList.setAgianDeduct(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100).toString());
        }
        result.add(satisfyList);
        return result;
    }


    /**
     * 设置加入商品不满足购物车时的提示语
     *
     * @param messageBuilder
     * @param discountList
     */
    private List<ActivityList> setMessageNoSatisfyCart(StringBuilder messageBuilder, List<CalculationDiscountBO.CalculationDiscountResult.Discount> discountList) {
        List<ActivityList> activityList = new ArrayList<>();
        discountList = discountList.parallelStream().filter(k -> (Objects.equals(ActivityTypeEnum.TYPE_11.getCode(), k.getType())
                || Objects.equals(ActivityTypeEnum.TYPE_12.getCode(), k.getType()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(discountList)) {
            return null;
        }
        //已减 X 元
        messageBuilder.append("已减 <span style=\"color:#fa5555\">")
                .append(WebUtil.formatAmount(discountList.get(0).getDiscount() * 1.00 / 100))
                .append("</span> 元");
        ActivityList noSatisfy = new ActivityList();
        noSatisfy.setTipType(5);
        noSatisfy.setDeduct(WebUtil.formatAmount(discountList.get(0).getDiscount() * 1.00 / 100).toString());
        activityList.add(noSatisfy);
        return activityList;
    }

    private List<ShoppingCartApportionBO.CartGoodsDetailDto> buyGift(CalculationDiscountBO.CalculationDiscountResult result, List<CartGoods> cartGoods, ActivityQueryDto activityQueryDto, ShoppingCartGoodsApportionBO baseRequestDTO){


        if (result == null || CollectionUtils.isEmpty(result.getGoods())) {
            return new ArrayList<>();
        }
        List<ProductBO> products = this.drawGiftInfo(result, baseRequestDTO);
        return this.gifAddCart(products, result);
    }

    private void addCalculationDiscountGoods(List<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods> calculationDiscountGoodsList,
                                             String goodsCode,String goodsId, Integer goodsQuantity, Long originalPrice, Integer memberDiscount,CartGoods cartGoods) {
        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods calculationDiscountGoods = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods();
        calculationDiscountGoods.setGoodsCode(goodsCode);
        calculationDiscountGoods.setGoodsId(goodsId);
        calculationDiscountGoods.setGoodsQuantity(goodsQuantity);
        calculationDiscountGoods.setOriginalPrice(originalPrice);
        calculationDiscountGoods.setMemberDiscount(memberDiscount);
        //新增咖啡月卡券券号
        calculationDiscountGoods.setCouponCode(cartGoods.getCouponCode());
        calculationDiscountGoods.setCartGoodsUid(cartGoods.getCartGoodsUid());

        ArrayList<ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material> materials = new ArrayList<>();
        //可选搭配
        if (cartGoods != null && CollectionUtils.isNotEmpty(cartGoods.getProductGroupList())) {
            for (CartGoods.ComboxGoods materialGoods : cartGoods.getProductGroupList()) {
                if("0".equals(materialGoods.getGoodsId())){
                    continue;
                }
                ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material material = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material();
                material.setType(2);
                material.setGoodsId(materialGoods.getGoodsId());
                material.setGoodsQuantity(materialGoods.getQty());
                material.setOriginalPrice(null != materialGoods.getFinalPrice() ?
                        materialGoods.getFinalPrice() : 0);
                materials.add(material);
            }
        }

        //固定商品
        if (cartGoods != null && CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            for (CartGoods.ComboxGoods materialGoods : cartGoods.getProductComboList()) {
                //加料
                if (CollectionUtils.isNotEmpty(materialGoods.getProductMaterialList())) {
                    for (CartGoods.MaterialGoods materialGoods2 : materialGoods.getProductMaterialList()) {
                        if (StringUtils.isEmpty(materialGoods2.getSpuId())) {
                            continue;
                        }
                        ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material material = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material();
                        material.setType(1);
                        material.setGoodsId(materialGoods2.getSpuId());
                        material.setGoodsQuantity(1);
                        material.setOriginalPrice(null != materialGoods2.getFinalPrice() ?
                                materialGoods2.getFinalPrice() : 0);
                        materials.add(material);
                    }
                }
            }
        }

        //加料
        if (null != cartGoods && CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            for (CartGoods.MaterialGoods materialGoods : cartGoods.getProductMaterialList()) {
                ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material material = new ActivityCalculationDiscountRequestDto.CalculationDiscountGoods.Material();
                material.setType(1);
                material.setGoodsId(materialGoods.getSpuId());
                material.setGoodsQuantity(1);
                material.setOriginalPrice(null != materialGoods.getOriginalPrice() ?
                        materialGoods.getOriginalPrice() : 0);
                material.setNowPrice(null != materialGoods.getFinalPrice() ? materialGoods.getFinalPrice().intValue():0);
                materials.add(material);
            }
        }
        calculationDiscountGoods.setSmallMaterial(materials);
        calculationDiscountGoodsList.add(calculationDiscountGoods);

    }

    private FullReductionBO fullReduction(ShoppingCartGoodsApportionBO baseRequestDTO, CalculationDiscountBO.CalculationDiscountResult discountResult, List<CartGoods> cartGoodsList, ActivityQueryDto activityQueryDto){

        FullReductionBO fullReduction = new FullReductionBO();


        List<ActivityTypeEnum> activityTypeEnums = new LinkedList<>();
        /**
         * 每满减 TYPE_11\ 阶梯满减 TYPE_12
         */
        activityTypeEnums.add(ActivityTypeEnum.TYPE_11);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_12);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_3);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_31);

        GetActivityBO getActivityBO = new GetActivityBO();
        getActivityBO.setActivityQueryDto(activityQueryDto);
        getActivityBO.setActivityTypeEnums(activityTypeEnums);
        ActivityBO activityBO = promotionManager.queryActivityByType(getActivityBO, baseRequestDTO.getManagerService().getPromotionService());
        fullReduction.setActivityBO(activityBO);
        if (activityBO == null){
            return fullReduction;
        }

        List<CalculationDiscountBO.CalculationDiscountResult.Discount> discounts = discountResult.getDiscounts();
        List<CalculationDiscountBO.CalculationDiscountResult.Discount> fullDiscountsList = discounts
                .stream()
                .filter(d -> ActivityTypeEnum.TYPE_11.getCode().equals(d.getType()) || ActivityTypeEnum.TYPE_12.getCode().equals(d.getType()))
                .collect(Collectors.toList());
        /**
         * 设置到响应中 总的满减优惠金额
         */
        if (CollectionUtils.isNotEmpty(fullDiscountsList)) {

            long fullDiscount = 0L;
            fullDiscount = fullDiscountsList.stream().filter(d -> d.getDiscount() != null).mapToLong(CalculationDiscountBO.CalculationDiscountResult.Discount::getDiscount).sum();
            fullReduction.setDiscount(fullDiscount);
        }

        List<Integer> typeEnums = activityTypeEnums.stream().map(ActivityTypeEnum::getCode).collect(Collectors.toList());
        /**
         * 还原满减折扣到行记录上
         */
        Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods> map = discountResult.getGoods()
                .stream()
                .filter(g -> null != g.getCartGoodsUid())
                .collect(Collectors.toMap(CalculationDiscountBO.CalculationDiscountResult.Goods::getCartGoodsUid, Function.identity(), (k1, k2) -> k1));

        long full = 0L;
        long sum = 0L;
        for (CartGoods cart : cartGoodsList) {
            CalculationDiscountBO.CalculationDiscountResult.Goods discountMap = map.get(cart.getCartGoodsUid());
            full = 0L;
            sum = 0L;
            if (null==discountMap) continue;
            if (CollectionUtils.isNotEmpty(discountMap.getDiscounts())) {
                sum = discountMap.getDiscounts()
                        .stream()
                        .filter(d -> typeEnums.contains(d.getType()))
                        .mapToLong(CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount::getDiscount)
                        .sum();
                cart.setAmount(cart.getAmount() + sum);
            }
            //小料
            if (CollectionUtils.isNotEmpty(cart.getProductMaterialList())) {
                List<CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> materialDiscount = discountMap.getSmallMaterial();
                HashMap<String, Long> mDiscount = drawnFullDiscount(materialDiscount, typeEnums, 1);
                if (!mDiscount.isEmpty()) {
                    for (CartGoods.MaterialGoods mt : cart.getProductMaterialList()) {
                        Long md = mDiscount.get(mt.getSpuId());
                        if (md != null) {
                            mt.setAmount(mt.getAmount() + md);
                        }
                    }
                }
            }
            //可选商品
            if (CollectionUtils.isNotEmpty(cart.getProductGroupList())) {
                List<CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> materialDiscount = discountMap.getSmallMaterial();
                HashMap<String, Long> mDiscount = drawnFullDiscount(materialDiscount, typeEnums, 2);
                if (!mDiscount.isEmpty()) {
                    for (CartGoods.ComboxGoods com : cart.getProductGroupList()) {
                        Long md = mDiscount.get(com.getGoodsId());
                        if (md != null) {
                            com.setAmount(com.getAmount() + md);
                            cart.setAmount(cart.getAmount() + md);
                        }
                    }
                }
            }
        }
        return fullReduction;

    }


    private ShoppingCartContext convert2ShopingCartContext(ShoppingCartGoodsApportionBO baseRequestDTO){
        ShoppingCartContext cartContext = new ShoppingCartContext();
        cartContext.setMenuType(baseRequestDTO.getMenuType());
        cartContext.setOrderType(baseRequestDTO.getOrderType());
        cartContext.setPartnerId(baseRequestDTO.getPartnerId());
        cartContext.setShopId(baseRequestDTO.getShopId());
        cartContext.setUserId(baseRequestDTO.getUserId());
        cartContext.setSessionId(baseRequestDTO.getSessionId());
        cartContext.setTableNumber(baseRequestDTO.getTableNumber());
        return cartContext;
    }

    /**
     * 查询生态配置限制加购开关与限制数量
     */
    private Integer limitGoodsQty(List<CartGoods> oldCartGoodsList, CartGoods addGoods,String appid){
        Integer qty = 0;
        if(CollectionUtils.isNotEmpty(oldCartGoodsList)){
            for (CartGoods goods : oldCartGoodsList) {
                qty += goods.getQty();
            }
        }
        qty += addGoods.getQty();
        String redisKey = limitCartKey + appid;

        Object value = redisCache.hashGet(redisKey, "2");
        if (value == null) {
            return qty;
        } else {
            boolean bool = value.getClass().getName().equals("java.lang.String");
            if(bool){
                return qty;
            }
            JSONArray jsonArray = (JSONArray)value;
            int cartLimitFlag = 0;
            int cartLimitCount = 0;
            for (Object object : jsonArray){
                JSONObject jsonObject = (JSONObject)object;
                HashMap hashMap = JSONObject.parseObject(jsonObject.toJSONString(),HashMap.class);
                if("cartLimitFlag".equals(hashMap.get("appKey"))){
                    if (StringUtils.isBlank((String)hashMap.get("appValue"))) {
                        return qty;
                    }
                    cartLimitFlag = Integer.parseInt((String)hashMap.get("appValue"));
                }
                if("cartLimitCount".equals(hashMap.get("appKey"))){
                    if (StringUtils.isBlank((String)hashMap.get("appValue"))) {
                        return qty;
                    }
                    cartLimitCount = Integer.parseInt((String)hashMap.get("appValue"));
                }
            }
            if(cartLimitFlag == 1 && cartLimitCount != 0 && qty > cartLimitCount){
                throw new ServiceException(ResponseResult.SHOPPING_CART_LIMIT_ADD);
            }
        }
        return qty;
    }

    /**
     * 初始化价格
     */
    public ShoppingGoodsAmountBO initShoppingCart(CalculationDiscountBO calculationDiscountBO
            , List<CartGoods> cartGoodsList) {
        ShoppingGoodsAmountBO shoppingGoodsAmountBO = new ShoppingGoodsAmountBO();

        /**
         * 使用促销算价赋值行记录
         */
        List<CalculationDiscountBO.CalculationDiscountResult.Goods> goods = null;
        CalculationDiscountBO.CalculationDiscountResult discountResult = null;

        if (calculationDiscountBO != null && calculationDiscountBO.getResult() != null && CollectionUtils.isNotEmpty(calculationDiscountBO.getResult().getGoods())) {
            discountResult = calculationDiscountBO.getResult();
            goods = discountResult.getGoods();
        }
        long totalOriginalAmount = 0L, totalAmount = 0L, totalPackageAmount = 0L;
        long originalAmount = 0L, amount = 0L, packageAmount = 0L;
        for (CartGoods cartGoods : cartGoodsList) {
            originalAmount = 0L;amount = 0L;packageAmount = 0L;

            //原价行记录
            originalAmount = cartGoods.getOriginalPrice() * cartGoods.getQty();
            cartGoods.setOriginalAmount(originalAmount);

            this.rowRealAmount(goods, cartGoods);
            //成交价行记录
            amount = cartGoods.getAmount();
            totalAmount += amount;
            totalOriginalAmount += cartGoods.getOriginalAmount();

            //包装费行记录
            packageAmount = cartGoods.getPackPrice() * cartGoods.getQty();
            cartGoods.setPackPrice(packageAmount);
            totalPackageAmount += packageAmount;
        }
        shoppingGoodsAmountBO.setOriginalTotalAmount(discountResult == null ? totalOriginalAmount : discountResult.getOriginalTotalAmount());
        shoppingGoodsAmountBO.setTotalAmount(discountResult == null ? totalAmount : discountResult.getTotalAmount());
        shoppingGoodsAmountBO.setNewPackAmount(totalPackageAmount);
        shoppingGoodsAmountBO.setTotalDiscountAmount(discountResult == null ? 0L : discountResult.getTotalDiscountAmount());
        return shoppingGoodsAmountBO;
    }


    private void rowRealAmount(List<CalculationDiscountBO.CalculationDiscountResult.Goods> goods, CartGoods cartGoods) {

        CalculationDiscountBO.CalculationDiscountResult.Goods find = goods
                .stream().filter((k) -> k.getCartGoodsUid().equals(cartGoods.getCartGoodsUid()))
                .findFirst()
                .get();

        if (find == null) return;
        cartGoods.setAmount(find.getRealAmount());
        //cartGoods.setOriginalAmount(find.getOriginalPrice());
        /**
         * 套餐的原价
         */
        Long originPrice = 0L;
        if (CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            for (CartGoods.ComboxGoods com : cartGoods.getProductComboList()) {
                originPrice += com.getFinalPrice() * cartGoods.getQty() * com.getQty();
            }
        }
        /**
         * 可选搭配
         */
        if (CollectionUtils.isNotEmpty(cartGoods.getProductGroupList())) {
            Integer type2 = 2;
            Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> gChoices = find.getSmallMaterial()
                    .stream().filter(d -> type2.equals(d.getType()))
                    .collect(Collectors.toMap(CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial::getGoodsId, Function.identity(), (k1, k2) -> k1));
            long amount = 0L;

            //可选搭配
            for (CartGoods.ComboxGoods choice : cartGoods.getProductGroupList()) {
                CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial mt = gChoices.get(choice.getGoodsId());
                if (mt == null) {
                    amount += choice.getAmount() * choice.getQty();
                }
                else {
                    amount += mt.getRealAmount();
                    choice.setAmount(mt.getRealAmount().longValue());
                }
                originPrice += choice.getFinalPrice() * choice.getQty()*cartGoods.getQty();
            }
            cartGoods.setAmount(cartGoods.getAmount() + amount);
        }
        /**
         * 小料
         */
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            Integer type1 = 1;
            Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> sChoices = find.getSmallMaterial()
                    .stream().filter(d -> type1.equals(d.getType()))
                    .collect(Collectors.toMap(CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial::getGoodsId, Function.identity(), (k1, k2) -> k1));

            for (CartGoods.MaterialGoods mg : cartGoods.getProductMaterialList()) {
                CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial sm = sChoices.get(mg.getSpuId());
                if (sm != null) {
                    mg.setAmount(sm.getRealAmount().longValue());
                }
            }
        }
        if (GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
            cartGoods.setOriginalAmount(originPrice);
        }

    }

    /**
     * 抽取满减的折扣金额 按货对应
     * 小料和可选搭配
     */
    public HashMap<String, Long> drawnFullDiscount(List<CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial> materialDiscount, List<Integer> typeEnums, Integer type) {
        HashMap<String, Long> hashMap = new HashMap<>();
        if (CollectionUtils.isEmpty(materialDiscount)) return hashMap;
        for (CalculationDiscountBO.CalculationDiscountResult.Goods.SmallMaterial smallMaterial : materialDiscount) {
            if (CollectionUtils.isEmpty(smallMaterial.getDiscounts()) && !type.equals(smallMaterial.getType()))
                continue;
            for (CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount discount : smallMaterial.getDiscounts()) {
                if (typeEnums.contains(discount.getType())) {
                    Long aLong = hashMap.get(discount.getGoodsId()) == null ? 0L : hashMap.get(discount.getGoodsId());
                    hashMap.put(discount.getGoodsId(), aLong + discount.getDiscount());
                }
            }
        }
        return hashMap;
    }

    /**
     * 赠品detail
     *
     * @param discountResult
     */
    private List<ProductBO> drawGiftInfo(CalculationDiscountBO.CalculationDiscountResult discountResult, ShoppingCartGoodsApportionBO baseRequestDTO) {

        List<ProductBO> productBeanList = new ArrayList<>();
        List<String> gifts = this.getProductIdsForGift(discountResult);

        if (CollectionUtils.isEmpty(gifts)) return productBeanList;

        GetProductBO getProductBO = new GetProductBO();
        getProductBO.setGoodsId(gifts);
        getProductBO.setPartnerId(baseRequestDTO.getPartnerId());
        getProductBO.setStoreId(baseRequestDTO.getShopId());
        getProductBO.setMenuType(baseRequestDTO.getMenuType());
        List<ProductBO> productsInfo = productManager.getProductsInfo(getProductBO, baseRequestDTO.getManagerService().getProductService());

        return productsInfo;
    }

    /**
     * 抽取赠品
     * goodsId->goods
     *
     * @param discountResult
     * @return
     */
    private List<String> getProductIdsForGift(CalculationDiscountBO.CalculationDiscountResult discountResult) {

        List<String> gifts = new ArrayList<>();
        if (CollectionUtils.isEmpty(discountResult.getGoods())) {
            return gifts;
        }
        gifts = discountResult.getGoods()
                .stream()
                .filter(d -> CalculationGoodsType.TYPE_1.getType().equals(d.getCartGoodType()))
                .map(CalculationDiscountBO.CalculationDiscountResult.Goods::getGoodsId)
                .collect(Collectors.toList());
        return gifts;
    }

    public List<ShoppingCartApportionBO.CartGoodsDetailDto> gifAddCart(List<ProductBO> products , CalculationDiscountBO.CalculationDiscountResult discountResult) {
        List<ShoppingCartApportionBO.CartGoodsDetailDto> giftGoods = new ArrayList<>();
        Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods> discountForGift = this.getDiscountForGift(discountResult);

        for (ProductBO product : products) {
            String k = product.getSpuId();
            CalculationDiscountBO.CalculationDiscountResult.Goods goods = discountForGift.get(k);
            CalculationDiscountBO.CalculationDiscountResult.Goods.GoodsDiscount discount = goods.getDiscounts()
                    .stream()
                    .filter(g -> ActivityTypeEnum.TYPE_63.getCode().equals(g.getType()) ||ActivityTypeEnum.TYPE_62.getCode().equals(g.getType()) || ActivityTypeEnum.TYPE_61.getCode().equals(g.getType()))
                    .findFirst()
                    .get();
            ShoppingCartApportionBO.CartGoodsDetailDto cartGoodsDetailDto = new ShoppingCartApportionBO.CartGoodsDetailDto();
            cartGoodsDetailDto.setOriginalGoodsUid(goods.getOriginalGoodsUid());
            cartGoodsDetailDto.setCartGoodsUid(goods.getCartGoodsUid());
            cartGoodsDetailDto.setTaxId(product.getTaxId());
            cartGoodsDetailDto.setTax(product.getTax());
            cartGoodsDetailDto.setSpuId(product.getPid());
            cartGoodsDetailDto.setSpuName(product.getName());
            cartGoodsDetailDto.setSkuId(goods.getGoodsId());
            cartGoodsDetailDto.setSkuName(product.getName());
            cartGoodsDetailDto.setSalePrice(product.getOriginalPrice());
            cartGoodsDetailDto.setPicture(product.getPicture());
            cartGoodsDetailDto.setQty(goods.getGoodsQuantity());
            cartGoodsDetailDto.setActivityType(discount.getType());
            cartGoodsDetailDto.setNodeId(discount.getActivityCode());
            cartGoodsDetailDto.setCategoryName(product.getCategoryName());
            cartGoodsDetailDto.setStockLimit(ObjectUtils.equals(1, product.getStockLimit()));
            cartGoodsDetailDto.setProductCode(product.getCustomerCode());
            cartGoodsDetailDto.setCustomerCode(product.getCustomerCode());
            cartGoodsDetailDto.setWeight(product.getWeight());
            cartGoodsDetailDto.setUnit(product.getUnit());
            cartGoodsDetailDto.setActivityDiscountsDtos(new ArrayList<>());
            cartGoodsDetailDto.setClassificationId(product.getCategory());
            cartGoodsDetailDto.setClassificationName(product.getCategoryName());
            cartGoodsDetailDto.setOriginalPrice(product.getOriginalPrice());
            cartGoodsDetailDto.setTotalDiscountAmount(goods.getDiscountAmount().intValue());
            List<ActivityDiscountsDto> activityDto = new ArrayList<>();

            ActivityDiscountsDto dto = new ActivityDiscountsDto();
            dto.setActivityCode(discount.getActivityCode());
            dto.setActivityName(discount.getActivityName());
            dto.setActivityType(discount.getType());
            dto.setDiscountAmount(discount.getDiscount().intValue());
            dto.setActualActivityGoodsNumber(discount.getActualGoodsNumber());
            activityDto.add(dto);
            cartGoodsDetailDto.setActivityDiscountsDtos(activityDto);
            giftGoods.add(cartGoodsDetailDto);
        }
        return giftGoods;
    }

    public Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods> getDiscountForGift(CalculationDiscountBO.CalculationDiscountResult discountResult) {

        Map<String, CalculationDiscountBO.CalculationDiscountResult.Goods> gifts = discountResult.getGoods()
                .stream()
                .filter(d -> CalculationGoodsType.TYPE_1.getType().equals(d.getCartGoodType()))
                .collect(Collectors.toMap(CalculationDiscountBO.CalculationDiscountResult.Goods::getGoodsId, Function.identity(), (k1, k2) -> k1));
        return gifts;
    }


    /**
     * 构建用户可以商品券信息
     *
     * @param discountResult
     * @return
     */
    private List<ChooseGoodsBO> buildSendGoods(CalculationDiscountBO.CalculationDiscountResult discountResult) {

        // 赠送、换购商品信息集合
        List<CalculationDiscountBO.CalculationDiscountResult.SendActivity> sendGoods = discountResult.getSendGoods();
        if (sendGoods == null || sendGoods.isEmpty()) {
            return null;
        }

        // 抽取买一赠一寄件活动送的商品
        List<CalculationDiscountBO.CalculationDiscountResult.SendActivity> buyOneGiveOneSendGoods = sendGoods
                .stream()
                .filter(sendGood -> ObjectUtils.equals(sendGood.getActivityType(), ActivityTypeEnum.TYPE_63.getCode()))
                .collect(Collectors.toList());

        if (null == buyOneGiveOneSendGoods || buyOneGiveOneSendGoods.isEmpty()) {
            return null;
        }

        List<ChooseGoodsBO> chooseGoods =  new ArrayList<>() ;
        buyOneGiveOneSendGoods.forEach(sendActivity -> {

            // 这个是真正的送的券
            List<CalculationDiscountBO.CalculationDiscountResult.SendActivity.SendGoods> innerSendGoods = sendActivity.getSendGoods();
            if (innerSendGoods == null || innerSendGoods.isEmpty()) {
                return;
            }

            innerSendGoods.forEach(innerSendGood -> {
                ChooseGoodsBO chooseGood = new ChooseGoodsBO();
                chooseGood.setActiveCode(sendActivity.getActivityCode());
                chooseGood.setActiveType(sendActivity.getActivityType());
                chooseGood.setGoodsId(innerSendGood.getGoodsId());
                chooseGood.setQty(innerSendGood.getSendNumber());
                chooseGood.setCouponQty(1);
                chooseGood.setCartGoodsUid(innerSendGood.getOriginalGoodsUid());
                chooseGood.setCouponCode(innerSendGood.getSendCouponCode());
                chooseGood.setCouponName(innerSendGood.getSendCouponName());
                chooseGood.setSendCoupon(innerSendGood.getSendCoupon());
                chooseGood.setGoodsName(innerSendGood.getGoodsName());
                chooseGoods.add(chooseGood);
            });

        });
        return chooseGoods;
    }


    /**
     * 处理加价购商品
     *
     * @param sendGoodsList
     * @param partnerId
     * @param storeId
     */
    private void processSendGoods(List<ShoppingCartGoodsApportionBO.SendGoods> sendGoodsList
            , String partnerId, String storeId,String menuType, ShoppingCartBaseService shoppingCartService) {
        List<String> goodsIds = sendGoodsList.parallelStream().map(ShoppingCartGoodsApportionBO.SendGoods::getGoodsId).collect(Collectors.toList());
        List<ProductBeanDTO> productBeanList =
                assortmentSdkService.getProductsInfoSdk(partnerId, storeId, goodsIds, menuType, shoppingCartService);
        // 将productBeanList转换为Map，key为pid，即goodsId
        Map<String, ProductBeanDTO> productBeanMap = productBeanList.parallelStream()
                .collect(Collectors.toMap(ProductBeanDTO::getPid, Function.identity(), (k1, k2) -> k1));
        // 遍历购物车进行加个更新
        for (ShoppingCartGoodsApportionBO.SendGoods sendGoods : sendGoodsList) {
            ProductBeanDTO productBean;
            if ((productBean = productBeanMap.get(sendGoods.getGoodsId())) != null) {
                // 设置加价购商品原价
                sendGoods.setOriginalPrice(productBean.getFinalPrice());
            } else {
                throw new ServiceException(ResponseResult.SHOPPING_CART_SENDGOODS_NOT_EXIST);
            }
        }

    }

}
