package cn.freemud.demo.service;

import cn.freemud.adapter.ActivityAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.constant.ShoppingCartConstant;
import cn.freemud.demo.GetActivityBO;
import cn.freemud.demo.ValidateShopProductRequestBO;
import cn.freemud.demo.constant.ResponseConstant;
import cn.freemud.demo.entities.*;
import cn.freemud.demo.entities.bo.goods.GetProductBO;
import cn.freemud.demo.entities.bo.goods.GetProductBySkuIdResponseBO;
import cn.freemud.demo.entities.bo.goods.PlatformProductBO;
import cn.freemud.demo.entities.bo.goods.ProductBO;
import cn.freemud.demo.entities.bo.goods.add.BaseAddGoodsBO;
import cn.freemud.demo.entities.dto.BaseRequestDTO;
import cn.freemud.demo.manager.coupon.CouponManager;
import cn.freemud.demo.manager.coupon.CouponService;
import cn.freemud.demo.manager.product.ProductManager;
import cn.freemud.demo.manager.customer.CustomerManager;
import cn.freemud.demo.manager.product.ProductService;
import cn.freemud.demo.manager.promotion.PromotionManager;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
import cn.freemud.entities.dto.activity.ActivityQueryResponseDto;
import cn.freemud.entities.dto.calculate.CalculationSharingDiscountRequestDto;
import cn.freemud.entities.dto.calculate.CalculationSharingDiscountResponseDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.*;
import cn.freemud.interceptor.BizServiceException;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.impl.AssortmentSdkService;
import cn.freemud.service.impl.calculate.CalculationCommonService;
import cn.freemud.utils.BeanUtil;
import cn.freemud.utils.WebUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.productcenter.domain.ProductBeanDTO;
import com.freemud.application.sdk.api.productcenter.request.product.valid.ValidateShopProductRequest;
import com.freemud.application.sdk.api.productcenter.request.product.valid.ValidateShopProductType;
import com.freemud.application.sdk.api.productcenter.response.ProductResponseDTO;
import com.freemud.application.sdk.api.productcenter.response.valid.ValiadShopProductResponse;
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.impl.ShoppingCartBaseServiceImpl;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
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.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public abstract class AbstractAddGoodsService implements AddGoodsService {

    @Autowired
    private CustomerManager customerManager;

    @Autowired
    private ProductManager productManager;

    @Autowired
    private CouponManager couponManager;

    @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_";




    /**
     * 加车的流程
     *
     * @return
     */
    public final ShoppingCartGoodsBO addGoods(BaseAddGoodsBO addGoodsBO) {
        // 基本参数校验
        this.checkParams(addGoodsBO);

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

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

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

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

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

        // 拼装购物车价格
        SetMessageBO setMessageBO = this.distribute(addGoodsBO, distributeBO);

        // 提示语设置,例如满减信息
        ShoppingCartGoodsBO addGoodsShoppingCartBO = this.setMessage(addGoodsBO, setMessageBO);

        return addGoodsShoppingCartBO;
    }

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

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

        return customSetMessageBO;
    }

    public final CalCostBO getDiscountResult(BaseAddGoodsBO 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 SetMessageBO distribute(BaseAddGoodsBO addGoodsBO, DistributeBO distributeBO) {
        SetMessageBO commonSetMessageBO = this.commDistribute(addGoodsBO, distributeBO);

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

        return customSetMessageBO;
    }

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

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

        return customAddGoodsShoppingCartBO;
    }


    /**
     * 请求基本参数校验
     * @return
     */
    public final BaseResponse checkParams(BaseAddGoodsBO 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(BaseAddGoodsBO 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());

        // 获取商品信息
        GetProductBO getProductBO = convert2ProductBO(baseRequestBO);
        List<ProductBO>  productsInfoList = productManager.getProductsInfo(getProductBO, baseRequestBO.getManagerService().getProductService());
        ProductBO productsInfo = productsInfoList.get(0);
        bo.setProduct(productsInfo);

        // 获取购物车信息
        // 注意，围餐和点餐redis数据结构不一样
        List<CartGoods> allCartGoodsList = assortmentSdkService.getShoppingCart(baseRequestBO.getPartnerId(), baseRequestBO.getShopId(), userInfo.getUserId(), baseRequestBO.getSessionId(), null, shoppingCartBaseService);
        if (CollectionUtils.isEmpty(allCartGoodsList)) {
            allCartGoodsList = new ArrayList<>();
        }
        // 转换商品券购物车添加的商品
        if (baseRequestBO.getSpuId().startsWith(CommonsConstant.COUPON_PREFIX)) {
            CartGoods cartGoods = baseRequestBO.getAddGoods();
            cartGoods.setCartGoodsUid(baseRequestBO.getSpuId());
            // 设置商品类型为商品券
            if (CouponTypeEnum.TYPE_4.getCode().equals(getProductBO.getCouponType())) {
                cartGoods.setGoodsType(GoodsTypeEnum.HG_COUPON_GOODS.getGoodsType());
            } else {
                cartGoods.setGoodsType(GoodsTypeEnum.COUPON_GOODS.getGoodsType());
            }
            // 商品券Id
            String spqId = baseRequestBO.getSpuId().substring(CommonsConstant.COUPON_PREFIX.length());
            cartGoods.setSpuId(spqId);
            cartGoods.setSkuId(productsInfo.getSkuId());
            cartGoods.setOriginalPrice(0L);
            cartGoods.setOriginalAmount(0L);
            cartGoods.setAmount(0L);
            cartGoods.setPackPrice(productsInfo.getPackPrice());
            cartGoods.setPic(productsInfo.getPicture());
            cartGoods.setWeight(productsInfo.getWeight());
            cartGoods.setUnit(productsInfo.getUnit());
            boolean stockLimit = false;
            if (productsInfo.getType() == ProductType.NOSPEC.getCode()
                    && productsInfo.getStockLimit() == 1) {
                stockLimit = true;
            } else {
                for (ProductBO.SkuProductBean skuProductBean : productsInfo.getSkuList()) {
                    if (productsInfo.getSkuId().equals(skuProductBean.getSkuId()) && skuProductBean.getStockLimit() == 1) {
                        stockLimit = true;
                        break;
                    }
                }
            }
            cartGoods.setStockLimit(stockLimit);

        }
        List<CartGoods> oldCartGoodsList = BeanUtil.convertBeans(allCartGoodsList, CartGoods::new);
        bo.setCartGoods(oldCartGoodsList);

        return bo;
    }

    private GetCouponDetailBO convert2GetCouponDetailBO(BaseAddGoodsBO baseRequestBO) {
        GetCouponDetailBO getCouponDetailBO = new GetCouponDetailBO();
        getCouponDetailBO.setPartnerId(baseRequestBO.getPartnerId());
        getCouponDetailBO.setCouponCode(baseRequestBO.getCouponCode());
        getCouponDetailBO.setStoreCode(baseRequestBO.getShopId());

        return getCouponDetailBO;
    }

    private GetProductBO convert2ProductBO(BaseAddGoodsBO baseRequestBO) {
        GetProductBO getProductBO = new GetProductBO();
        GetCouponDetailBO getCouponDetail = convert2GetCouponDetailBO(baseRequestBO);
        getProductBO.setStoreId(baseRequestBO.getShopId());
        getProductBO.setMenuType(baseRequestBO.getMenuType());
        getProductBO.setPartnerId(baseRequestBO.getPartnerId());

        if (baseRequestBO.getSpuId().startsWith(CommonsConstant.COUPON_PREFIX)) {
            // 如果是商品券,获取商品券信息
            CouponDetailBO couponDetail = couponManager.getCouponDetail(getCouponDetail, baseRequestBO.getManagerService().getCouponService());

            if (couponDetail == null || !couponDetail.getResult().equals(ResponseCodeConstant.RESPONSE_SUCCESS_1) || CollectionUtils.isEmpty(couponDetail.getDetails())) {
                return null;
            }
            if (CollectionUtils.isEmpty(couponDetail.getDetails())) {
                return null;
            }
            Integer couponType = 0;
            boolean productValid = false;
            for (CouponDetailBO.Details detail : couponDetail.getDetails()) {
                if (productValid) break;
                if (!CouponStatus.STATUS_0.getCode().equals(detail.getStatus())) continue;
                for (CouponDetailBO.ActiveProduct activeProduct : detail.getActiveProduct()) {
                    if (baseRequestBO.getSkuId().equals(activeProduct.getProductIdPartner())) {
                        productValid = true;
                        couponType = detail.getType();
                        break;
                    }
                }
            }
            //检查商品是否有效
            if (!productValid) {
                return null;
            }
            // 判断该券是否在这个门店下(一个券可以在多个门店下使用)
            List<String> couPonstoreIds = Lists.newArrayList();
            for (CouponDetailBO.Details detail : couponDetail.getDetails()) {
                if (!CouponStatus.STATUS_0.getCode().equals(detail.getStatus())) continue;
                for (CouponDetailBO.ActiveRestrictionVOS activeRestrictionVO : detail.getActiveRestrictionVOS()) {
                    couPonstoreIds.add(activeRestrictionVO.getStoreIdPartner());
                }
            }
            if (CollectionUtils.isNotEmpty(couPonstoreIds) && !couPonstoreIds.contains(baseRequestBO.getShopId())) {
                return null;
            }

            //券返回的商品id
            List<String> skuIds = Lists.newArrayList();
            String skuId = baseRequestBO.getSpuId();
            skuIds.add(skuId);
            // 通过skuid查询spuid
            GetProductBySkuIdBO getProductBySkuIdBO = convert2GetProductBySkuIdBO(baseRequestBO);
            Map<String, GetProductBySkuIdResponseBO> productsInfoBySkuIds = productManager.getProductsInfoBySkuIds(getProductBySkuIdBO, baseRequestBO.getManagerService().getProductService());
            GetProductBySkuIdResponseBO productsVo = productsInfoBySkuIds.get(skuId);
            if (null == productsVo || !Objects.equals(productsVo.getStatus(), StoreItemStatus.PUT_ON_SALE.getCode())) {
                return null;
            }
            getProductBO.setSpuid(Collections.singletonList(productsVo.getSpuId()));
            getProductBO.setSkuid(Collections.singletonList(productsVo.getSkuId()));
            getProductBO.setCouponType(couponType);
        } else {
            getProductBO.setSkuid(Collections.singletonList(baseRequestBO.getSkuId()));
            getProductBO.setSpuid(Collections.singletonList(baseRequestBO.getSpuId()));
        }

        return getProductBO;
    }

    private GetProductBySkuIdBO convert2GetProductBySkuIdBO(BaseAddGoodsBO baseRequestBO) {
        GetProductBySkuIdBO getProductBySkuIdBO = new GetProductBySkuIdBO();
        getProductBySkuIdBO.setMenuType(baseRequestBO.getMenuType());
        getProductBySkuIdBO.setPartnerId(baseRequestBO.getPartnerId());
        List<String> skuids = new ArrayList<>();
        skuids.add(baseRequestBO.getSkuId());
        getProductBySkuIdBO.setSkuids(skuids);
        getProductBySkuIdBO.setStoreId(baseRequestBO.getShopId());
        return getProductBySkuIdBO;
    }

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


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

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

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

        return customCalCostBO;
    }


    private BaseResponse checkCommParams(BaseAddGoodsBO baseRequestDTO) {

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

        return ResponseBuilder.success();
    }

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

        //购物车添加数量限制
        CartGoods addGoods = baseRequestDTO.getAddGoods();
        this.limitGoodsQty(checkBussinessRulesBO.getCartGoods(), addGoods, baseRequestDTO.getAppId());
        // 校验数量, 库存
        this.checkStocks(baseRequestDTO, checkBussinessRulesBO);
        // 校验套餐
        this.checkMeal(checkBussinessRulesBO.getCartGoods(), baseRequestDTO.getAddGoods());
        // 检查校验购物车商品(是否合法,上下架,点餐方式,是否在当前菜单中...),并移除非法商品
        ShoppingCartContext cartContext = convert2ShopingCartContext(baseRequestDTO);

        CheckCartRequest checkCartRequest = shoppingBaseService.checkShoppingCart(checkBussinessRulesBO.getCartGoods(), addGoods, cartContext);

        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(BaseAddGoodsBO baseRequestDTO, AddGoodsToShoppingCartBO addGoodsToShoppingCartBO) {
        DiscountResultBO calCostBO = new DiscountResultBO();
        List<CartGoods> cartGoods = shoppingBaseService.updateAndGetShoppingCart(addGoodsToShoppingCartBO.getCartGoods(), baseRequestDTO.getAddGoods(), addGoodsToShoppingCartBO.getShoppingCartContext());

        calCostBO.setCartGoods(cartGoods);
        calCostBO.setChanged(addGoodsToShoppingCartBO.getChanged());
        calCostBO.setShoppingCartContext(addGoodsToShoppingCartBO.getShoppingCartContext());
        calCostBO.setToastMsg(addGoodsToShoppingCartBO.getToastMsg());
        calCostBO.setIsMember(addGoodsToShoppingCartBO.getIsMember());

        return calCostBO;
    }

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

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

    private ShoppingCartGoodsBO setCommMessage(BaseAddGoodsBO baseRequestDTO, SetMessageBO setMessageBO) {

        ShoppingCartGoodsBO shoppingCartGoodsBO = setMessageBO.getShoppingCartGoodsBO();

        CalculationDiscountBO.CalculationDiscountResult discountResult = setMessageBO.getCalculationDiscountBO().getResult();

        // 满减提示

        StringBuilder messageBuilder = new StringBuilder();
        ActivityBO activityBO = setMessageBO.getActivityBO();
        List<ActivityList> activityList = null;
        if (discountResult == null || CollectionUtils.isEmpty(discountResult.getGoods())) {

            List<BenefitBeanBO> benefitBeanBOList = activityBO.getBenefits();
            BenefitBeanBO benefitBeanBO = benefitBeanBOList.get(0);
            //调用没有加入购物车的提示语的方法
            activityList = setMessageNotInShoppingCart(messageBuilder, activityBO, benefitBeanBOList, benefitBeanBO);


        }


        //促销返回满减提示语
        List<CalculationDiscountBO.CalculationDiscountResult.ActivityPrompt> activityPrompts = discountResult.getActivityPrompts();
        //List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> discounts = discountResult.getDiscounts();
        /**
         * 构建提示语
         */
        if (CollectionUtils.isNotEmpty(activityPrompts)) {
            activityList = setMessageSatisfyCart(messageBuilder, activityPrompts, activityBO);
        }
        else {
            activityList = setMessageNoSatisfyCart(messageBuilder, discountResult.getDiscounts());
        }

        /**
        * 调用促销统一活动查询,过滤出参与的满减(目前只有每满减和阶梯满减)
        */

        PromotionMessageDto promotionMessageDto = new PromotionMessageDto();
        if (activityBO != null){
            promotionMessageDto.setActivityId(activityBO.getActivityCode());
            promotionMessageDto.setActivityName(activityBO.getActivityName());
            promotionMessageDto.setActivityType(activityBO.getActivityType());
        }
        promotionMessageDto.setPromotionAmount(0L);
        promotionMessageDto.setPromotionMessage(messageBuilder.toString());
        ActivityTip activityTip = new ActivityTip();
        activityTip.setActivityCode(promotionMessageDto.getActivityId());
        activityTip.setActivityType(promotionMessageDto.getActivityType());
        activityTip.setActivityName(promotionMessageDto.getPromotionMessage());
        activityTip.setActivityList(activityList);
        shoppingCartGoodsBO.setActivityTip(activityTip);

        shoppingCartGoodsBO.setDeliveryFeeZeroReason(0);

        setToastMsgIfNotExist(shoppingCartGoodsBO, setMessageBO.getToastMsg());


        return shoppingCartGoodsBO;
    }

    private CalCostBO getComDiscountResult(BaseAddGoodsBO baseRequestDTO, DiscountResultBO discountResultBO, CalCostBO before) {

        CalculationDiscountBO calculationDiscountBO = promotionManager.calculationDiscount(before.getGetCalculationDiscountBO(), baseRequestDTO.getManagerService().getPromotionService());
        before.setCalculationDiscountBO(calculationDiscountBO);

        return before;
    }

    private SetMessageBO commDistribute(BaseAddGoodsBO baseRequestDTO, DistributeBO distributeBO) {

        SetMessageBO setMessageBO = new SetMessageBO();

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

        ShoppingCartGoodsBO shoppingCartGoodsBO = new ShoppingCartGoodsBO();

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

        // 满减
        FullReductionBO fullReductionBO = this.fullReduction(baseRequestDTO, distributeBO.getCalculationDiscountBO().getResult(), distributeBO.getCartGoods(), activityQueryDto);

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

        // 买一赠一寄杯
        List<ChooseGoodsBO> chooseGoodsBO = this.bugGiftAndSendCup(distributeBO.getCalculationDiscountBO().getResult(), distributeBO.getCartGoods(), activityQueryDto, baseRequestDTO);


        shoppingCartGoodsBO.setOriginalTotalAmount(shoppingGoodsAmountBO.getOriginalTotalAmount());
        shoppingCartGoodsBO.setNewPackAmount(null);
        shoppingCartGoodsBO.setTotalAmount(shoppingGoodsAmountBO.getTotalAmount());
        shoppingCartGoodsBO.setTotalDiscountAmount(shoppingGoodsAmountBO.getTotalDiscountAmount());

        shoppingCartGoodsBO.setFullDiscount(fullReductionBO.getDiscount());
        distributeBO.getCartGoods().addAll(giftGoods);
        shoppingCartGoodsBO.setChooseGoods(chooseGoodsBO);
        shoppingCartGoodsBO.setVersion(2);
        shoppingCartGoodsBO.setProducts(distributeBO.getCartGoods());
        shoppingCartGoodsBO.setProductsCount(distributeBO.getCartGoods().size());


        setMessageBO.setActivityBO(fullReductionBO.getActivityBO());
        setMessageBO.setShoppingCartGoodsBO(shoppingCartGoodsBO);
        setMessageBO.setCartGoods(distributeBO.getCartGoods());
        setMessageBO.setCalculationDiscountBO(distributeBO.getCalculationDiscountBO());

        return setMessageBO;
    }


    private ValidateShopProductRequestBO getValidateShopProductRequest(ProductBO product, BaseAddGoodsBO requestDto) {
        ValidateShopProductRequestBO request = new ValidateShopProductRequestBO();
        request.setChannel(requestDto.getMenuType());
        request.setPartnerId(requestDto.getPartnerId());
        request.setStoreId(requestDto.getShopId());
        List<ValidateShopProductType> productTypeList = new ArrayList<>();
        ValidateShopProductType productType = new ValidateShopProductType();

        productType.setAttributeList(null);
        productType.setComboProductTypeList(null);
        productType.setMemberDiscount(null);
        productType.setPrice(product.getFinalPrice().intValue());
        productType.setProductGroupTypeList(null);
        productType.setSkuId(product.getSkuId());
        productType.setSpuId(product.getSpuId());
        productType.setUuid(UUID.randomUUID().toString());
        productType.setValidateAttribute(0);
        productType.setValidatePrice(0);
        productType.setValidateStatuses(null);

        productTypeList.add(productType);
        request.setProductTypeList(productTypeList);
        return  request;

    }


    private List<ChooseGoodsBO> bugGiftAndSendCup(CalculationDiscountBO.CalculationDiscountResult result, List<CartGoods> cartGoods, ActivityQueryDto activityQueryDto, BaseAddGoodsBO 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
     * @param activityList
     */
    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<CartGoods> buyGift(CalculationDiscountBO.CalculationDiscountResult result, List<CartGoods> cartGoods, ActivityQueryDto activityQueryDto, BaseAddGoodsBO baseRequestDTO){


        if (result == null || CollectionUtils.isEmpty(result.getGoods())) {
            return null;
        }
        String menuType = baseRequestDTO == null ? null : baseRequestDTO.getMenuType();
        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(BaseAddGoodsBO 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(BaseAddGoodsBO 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;
    }

    private void checkStocks(BaseAddGoodsBO baseRequestDTO, CheckBussinessRulesBO checkBussinessRulesBO){
        GetProductStockRequestDto requestDto = new GetProductStockRequestDto();
        requestDto.setChannel(BusinessTypeEnum.getByType(baseRequestDTO.getMenuType()).getCode());
        requestDto.setPartnerId(baseRequestDTO.getPartnerId());
        requestDto.setStoreId(baseRequestDTO.getShopId());
        List<Long> productIds = new ArrayList<>();
        productIds.add(Long.parseLong(checkBussinessRulesBO.getProduct().getSkuId()));
        requestDto.setProductIds(productIds);


        ProductBO product = checkBussinessRulesBO.getProduct();
        ProductStockBO availableStocks = null;
        GetProductStock getProductStock = new GetProductStock();
        if (product.getType() == ProductType.NOSPEC.getCode()
                && product.getStockLimit() == 1) {
            List<ProductStockBO> productStock = productManager.getProductStock(getProductStock, baseRequestDTO.getManagerService().getProductService());
            if (CollectionUtils.isNotEmpty(productStock)){
                availableStocks = productStock.get(0);
            }

        } else {
            for (ProductBO.SkuProductBean skuProductBean : product.getSkuList()) {
                if (baseRequestDTO.getSkuId().equals(skuProductBean.getSkuId()) && skuProductBean.getStockLimit() == 1) {
                    List<ProductStockBO> productStock = productManager.getProductStock(getProductStock, baseRequestDTO.getManagerService().getProductService());
                    if (CollectionUtils.isNotEmpty(productStock)){
                        availableStocks = productStock.get(0);
                    }
                    break;
                }
            }
        }
        List<CartGoods> oldCartGoodsList = checkBussinessRulesBO.getCartGoods();
        CartGoods cartGoods = baseRequestDTO.getAddGoods();
        Integer qty = 0;
        if (CollectionUtils.isEmpty(oldCartGoodsList)) {
            qty = cartGoods.getQty();
        } else {
            qty = cartGoods.getQty();
            for (CartGoods goods : oldCartGoodsList) {
                if (goods.getSkuId().equals(cartGoods.getSkuId()) && goods.getSpuId().equals(cartGoods.getSpuId())) {
                    qty += goods.getQty();
                }
            }
        }
        if (availableStocks != null  &&
                (availableStocks.getQty() == null
                        || availableStocks.getQty() < qty)) {
            Integer stock = 0;
            if ((stock = availableStocks.getQty()) > 0) {
                throw new BizServiceException(ResponseResult.SHOPPING_CART_STOCK_NOT_HAVE, "仅剩" + stock + "件库存了");
            }
            throw new ServiceException(ResponseResult.SHOPPING_CART_STOCK_NOT_HAVE);
        }
    }


    private void checkMeal(List<CartGoods> cartGoodsList, CartGoods addGoods){

        if (GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType().equals(addGoods.getGoodsType())) {
            if (CollectionUtils.isEmpty(addGoods.getProductGroupList()) && CollectionUtils.isEmpty(addGoods.getProductComboList())) {
                throw new ServiceException(ResponseResult.SHOPPING_CART_NO_MEAL);
            }
        }

        for (CartGoods cartGoods : cartGoodsList){
            if (GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType().equals(addGoods.getGoodsType())) {
                if (CollectionUtils.isEmpty(addGoods.getProductGroupList()) && CollectionUtils.isEmpty(addGoods.getProductComboList())) {
                    throw new ServiceException(ResponseResult.SHOPPING_CART_NO_MEAL);
                }
            }
        }
    }

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

        /**
         * 使用促销算价赋值行记录
         */
        List<CalculationDiscountBO.CalculationDiscountResult.Goods> goods = null;
        if (discountResult != null && CollectionUtils.isNotEmpty(discountResult.getGoods())) {
            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, BaseAddGoodsBO baseRequestDTO) {

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

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

        GetProductBO getProductBO = new GetProductBO();

        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<CartGoods> gifAddCart(List<ProductBO> products , CalculationDiscountBO.CalculationDiscountResult discountResult) {
        List<CartGoods> 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();
            CartGoods cartGood = new CartGoods();
            cartGood.setGoodsId(goods.getGoodsId());
            cartGood.setGoodsType(1);
            cartGood.setSpuId(goods.getGoodsId());
            cartGood.setSkuId(goods.getGoodsId());
            cartGood.setOriginalPrice(product.getFinalPrice());
            cartGood.setPackPrice(product.getPackPrice());
            cartGood.setOriginalAmount(goods.getOriginalPrice() * goods.getGoodsQuantity());
            cartGood.setAmount(goods.getRealAmount());
            cartGood.setName(product.getName());
            cartGood.setSpuName(product.getName());
            cartGood.setCategoryName(product.getName());
            cartGood.setPic(product.getPicture());
            cartGood.setSkuName(product.getName());
            cartGood.setActivityType(discount.getType());
            cartGood.setStockLimit(ObjectUtils.equals(1, product.getStockLimit()));
            cartGood.setCustomerCode(product.getCustomerCode());
            cartGood.setUnit(product.getUnit());
            cartGood.setWeight(product.getWeight());
            cartGood.setQty(goods.getGoodsQuantity());
            cartGood.setClassificationId(product.getCategory());
            cartGood.setClassificationName(product.getCategoryName());
            // nodeId标识activeCode,用于计算均摊时每个商品在每个活动上均摊金额
            cartGood.setNodeId(discount.getActivityCode());
            giftGoods.add(cartGood);
        }
        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;
    }


}
