package cn.freemud.demo.service.impl;

import cn.freemud.adapter.ActivityAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.demo.constant.ResponseConstant;
import cn.freemud.demo.entities.bo.goods.ShoppingCartGoodsBO;
import cn.freemud.demo.entities.bo.coupon.CheckSpqBO;
import cn.freemud.demo.entities.bo.coupon.GetCheckSpqBo;
import cn.freemud.demo.entities.bo.coupon.GetCouponDetailBO;
import cn.freemud.demo.entities.bo.goods.*;
import cn.freemud.demo.entities.bo.goods.add.BaseAddGoodsBO;
import cn.freemud.demo.entities.bo.member.CustomerInfo;
import cn.freemud.demo.entities.bo.product.GetProductStock;
import cn.freemud.demo.entities.bo.product.ProductStockBO;
import cn.freemud.demo.entities.bo.promotion.ActivityBO;
//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.promotion.PromotionManager;
import cn.freemud.demo.service.AddGoodsService;
import cn.freemud.demo.service.DistributeService;
import cn.freemud.demo.service.MessageService;
import cn.freemud.demo.utils.CommonUtils;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
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.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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 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.stream.Collectors;

@Service
public abstract class AbstractAddGoodsService implements AddGoodsService {

    @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 DistributeService distributeService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private MessageService messageService;

    /**
     * 加车的流程
     *
     * @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());


        // 获取商品券换购券
        CheckSpqBO spqBO = getSpqInfo(baseRequestBO);

        GetProductBO getProductBO = convert2ProductBO(baseRequestBO, spqBO);
        // 获取商品信息
        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,null);
        if (CollectionUtils.isEmpty(allCartGoodsList)) {
            allCartGoodsList = new ArrayList<>();
        }
        bo.setCartGoods(allCartGoodsList);

        // 转换商品券购物车添加的商品
        if (Objects.nonNull(spqBO)) {
            CartGoods cartGoods = baseRequestBO.getAddGoods();
//            cartGoods.setCartGoodsUid(baseRequestBO.getSpuId());
//            cartGoods.setOriginalPrice(spqBO.getProductPrice());

            // 商品券Id
            if (CollectionUtils.isEmpty(cartGoods.getExtra())){
                cartGoods.setExtra(spqBO.getExtra());
            }
            cartGoods.setSpecProductId(spqBO.getSpecProductId());
            cartGoods.setSubName(spqBO.getSubName());
            cartGoods.setName(spqBO.getCouponName());
//            cartGoods.setSpuName(spqBO.getSpuName());
            cartGoods.setGoodsId(baseRequestBO.getSpuId());
            String spuId = baseRequestBO.getSpuId();
            String couponCode = CommonUtils.getCouponCode(baseRequestBO.getCouponCode(), spuId);

            cartGoods.setAddCartTime(System.currentTimeMillis());
            cartGoods.setSpuId(couponCode);
            cartGoods.setSkuId(StringUtils.isEmpty(spqBO.getSkuId()) ? spqBO.getSpuId() : spqBO.getSkuId());
            cartGoods.setOriginalPrice(0L);
            cartGoods.setOriginalAmount(0L);
            cartGoods.setAmount(0L);
            cartGoods.setQty(1);
//            cartGoods.setAmount(spqBO.getProductPrice());
            cartGoods.setCouponCode(baseRequestBO.getSpuId().substring(CommonsConstant.COUPON_PREFIX.length()));
            cartGoods.setPackPrice(productsInfo.getPackPrice());
            cartGoods.setPic(productsInfo.getPicture());
            cartGoods.setWeight(productsInfo.getWeight());
            cartGoods.setUnit(productsInfo.getUnit());
            cartGoods.setSpuName(productsInfo.getName());
            cartGoods.setCouponProductPrice(productsInfo.getFinalPrice());
            boolean stockLimit = false;
            if (productsInfo.getType() == ProductType.NOSPEC.getCode()
                    && productsInfo.getStockLimit() == 1) {
                stockLimit = true;
            } else {
                for (ProductBO.SkuProductBean skuProductBean : productsInfo.getSkuList()) {
                    if (baseRequestBO.getSkuId().equals(skuProductBean.getSkuId()) && skuProductBean.getStockLimit() == 1) {
                        stockLimit = true;
                        break;
                    }
                }
            }
            cartGoods.setStockLimit(stockLimit);

        }
        return bo;
    }

    private GetCouponDetailBO convert2GetCouponDetailBO(BaseAddGoodsBO baseRequestBO) {
        GetCouponDetailBO getCouponDetailBO = new GetCouponDetailBO();
        getCouponDetailBO.setPartnerId(baseRequestBO.getPartnerId());
        getCouponDetailBO.setCouponCode(StringUtils.isBlank(baseRequestBO.getCouponCode()) ? baseRequestBO.getSpuId().substring(CommonsConstant.COUPON_PREFIX.length()) : baseRequestBO.getCouponCode());
        getCouponDetailBO.setStoreCode(baseRequestBO.getShopId());

        return getCouponDetailBO;
    }

    private CheckSpqBO getSpqInfo(BaseAddGoodsBO baseRequestBO) {

        if (!CommonUtils.isProductCoupon(baseRequestBO.getCouponCode(), baseRequestBO.getSpuId())) {
            return null;
        }

        String spuId = baseRequestBO.getSpuId();
        String couponCode = CommonUtils.getCouponCode(baseRequestBO.getCouponCode(), spuId);

        GetCheckSpqBo getCheckSpqBo = new GetCheckSpqBo(baseRequestBO.getPartnerId(), couponCode,
                baseRequestBO.getShopId(), baseRequestBO.getMenuType(), baseRequestBO.getSpuId(), baseRequestBO.getSkuId(), baseRequestBO.getManagerService().getProductService());
        // 验证商品券和换购券
        CheckSpqBO checkSpqBO = couponService.checkSpq(getCheckSpqBo);
        if (checkSpqBO == null) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_COUPON_MIX_NOT_EXIST);
        }
        if (checkSpqBO.getDetails() != null) {
            checkSpqBO.setCouponName(checkSpqBO.getDetails().getTitle());
        }
        return checkSpqBO;
    }

    private GetProductBO convert2ProductBO(BaseAddGoodsBO baseRequestBO, CheckSpqBO checkSpqBO) {
        GetProductBO getProductBO = new GetProductBO();
        getProductBO.setStoreId(baseRequestBO.getShopId());
        getProductBO.setMenuType(baseRequestBO.getMenuType());
        getProductBO.setPartnerId(baseRequestBO.getPartnerId());
        if (checkSpqBO != null) {
            getProductBO.setGoodsId(Collections.singletonList(checkSpqBO.getSkuId()));
            getProductBO.setCouponType(checkSpqBO.getType());
            getProductBO.setActivityCode(checkSpqBO.getDetails().getActive().getActiveCode());
        } else {
            String goodsId = StringUtils.isEmpty(baseRequestBO.getSkuId()) ? baseRequestBO.getSpuId() : baseRequestBO.getSkuId();
            getProductBO.setGoodsId(Collections.singletonList(goodsId));
        }
        return getProductBO;
    }

    /**
     * 具体业务逻辑校验, 例如商品数量,库存等校验
     *
     * @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())){
            return ResponseUtil.error(ResponseResult.SHOPPING_CART_SHOP_ID_NOT_EMPTY);
//            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(),baseRequestDTO.getPartnerId());

        // 校验数量, 库存
        this.checkStocks(baseRequestDTO, checkBussinessRulesBO);

        // 校验套餐
        this.checkMeal(checkBussinessRulesBO.getCartGoods(), baseRequestDTO.getAddGoods());


        // 检查商品小料数量
        this.checkMaterialQty(addGoods,checkBussinessRulesBO.getProduct());


        // 检查校验购物车商品(是否合法,上下架,点餐方式,是否在当前菜单中...),并移除非法商品
        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 void checkMaterialQty(CartGoods addGoods, ProductBO product){
        Integer materialMaxQty = product.getMaxNum();
        int addProductQty = 0;
        if(CollectionUtils.isNotEmpty(addGoods.getProductMaterialList())){
            for(CartGoods.MaterialGoods materialRequestVo : addGoods.getProductMaterialList()){
                addProductQty = addProductQty + (materialRequestVo.getQty() == null ? 0 : materialRequestVo.getQty());
            }

        }
        if(materialMaxQty == null || ObjectUtils.equals(materialMaxQty, 0) || ObjectUtils.equals(addProductQty, 0)){
            return ;
        }

        if(addProductQty <= materialMaxQty){
            return ;
        }
        throw new ServiceException(ResponseResult.SHOPPING_CART_MATERIA_QTY_LIMIT_ERR);
    };

    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.setValidCouponMap(addGoodsToShoppingCartBO.getValidCouponMap());
        calCostBO.setSpqIdToCartUuidMap(addGoodsToShoppingCartBO.getSpqIdToCartUuidMap());
        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 = messageService.fullReduceMessage(discountResult, messageBuilder, activityBO);
        /**
        * 调用促销统一活动查询,过滤出参与的满减(目前只有每满减和阶梯满减)
        */

        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) {

        if (before.getGetCalculationDiscountBO() == null){
            before.setCalculationDiscountBO(new CalculationDiscountBO());
            return before;
        }
        CalculationDiscountBO calculationDiscountBO = promotionManager.calculationDiscount(before.getGetCalculationDiscountBO(), baseRequestDTO.getManagerService().getPromotionService());
        calculationDiscountBO.getResult().setValidCouponMap(before.getValidCouponMap());
        calculationDiscountBO.getResult().setSpqIdToCartUuidMap(before.getSpqIdToCartUuidMap());
        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 = distributeService.initShoppingCart(distributeBO.getCalculationDiscountBO().getResult(), distributeBO.getCartGoods(), null);

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

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

        // 买一赠一寄杯
        List<ChooseGoodsBO> chooseGoodsBO = distributeService.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());
        if (distributeBO.getCartGoods() == null){
            distributeBO.setCartGoods(new ArrayList<>());
        }
        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 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(ActivityPromptEnum.TipTypeEnum.ONE.getCode());
            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(ActivityPromptEnum.TipTypeEnum.TWO.getCode());
                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) {

            if(ActivityPromptEnum.PreferentialTypeEnum.TO_ORDER_ITEM_QUANTITY.getCode().equals(activityResponseDto.getCouponType())) {
                messageBuilder.append("满 <span style=\"color:#fa5555\">")
                        .append(activityPrompt.getThresholdQuantity())
                        .append("</span>件 减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100))
                        .append("</span> ")
                        .append("还差 <span style=\"color:#fa5555\">")
                        .append(activityPrompt.getThresholdQuantity() - activityPrompt.getTotalQuantity())
                        .append("</span> 件");
                // 满足 X 元 减 Y 元 还差 Z元
                satisfyList.setTipType(ActivityPromptEnum.TipTypeEnum.ELEVEN.getCode());
                satisfyList.setSatisfy(activityPrompt.getThresholdQuantity().toString());
                satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100).toString());
                satisfyList.setMissing((activityPrompt.getThresholdQuantity() - activityPrompt.getTotalQuantity())+ "");
                satisfyList.setInvokeAmount(WebUtil.formatAmount(activityResponseDto.getDelayTimes() * 1.00 / 100).toString());
            }else{
                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(ActivityPromptEnum.TipTypeEnum.THREE.getCode());
                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();
            }
            if(ActivityPromptEnum.PreferentialTypeEnum.TO_ORDER_ITEM_QUANTITY.getCode().equals(activityResponseDto.getCouponType())) {
                messageBuilder.append("已减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100))
                        .append("</span> 元 再买 <span style=\"color:#fa5555\">")
                        .append(activityPrompt.getThresholdQuantity() - activityPrompt.getTotalQuantity())
                        .append("</span> 件减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100))
                        .append("</span> 元");
                satisfyList.setTipType(ActivityPromptEnum.TipTypeEnum.TWELVE.getCode());
                satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100).toString());
                satisfyList.setAgainBuy((activityPrompt.getThresholdQuantity() - activityPrompt.getTotalQuantity())+"");
                satisfyList.setAgianDeduct(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100).toString());
                satisfyList.setInvokeAmount(WebUtil.formatAmount(activityResponseDto.getDelayTimes() * 1.00 / 100).toString());
            }
            else{
                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(ActivityPromptEnum.TipTypeEnum.FOUR.getCode());
                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());

            }
                //已减 X 元 再买 Y 元 减 Z 元
             }
        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 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,String partnerId) {
        Integer qty = 0;
        if (CollectionUtils.isNotEmpty(oldCartGoodsList)) {
            for (CartGoods goods : oldCartGoodsList) {
                qty += goods.getQty();
            }
        }
        qty += addGoods.getQty();

        int cartLimitCount = 0;
        String redisKey = RedisUtil.limitCart + partnerId + "_" + appid;
        //购物车内部缓存
        String value = redisCache.hashGet(redisKey, "cartLimitType");
        if (StringUtils.isNotBlank(value)) {
            cartLimitCount =  Integer.parseInt(value);
        }

//        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 (cartLimitFlag != 1) {
//                        return qty;
//                    }
//                }
//                if ("cartLimitCount".equals(hashMap.get("appKey"))) {
//                    if (StringUtils.isBlank((String) hashMap.get("appValue"))) {
//                        return qty;
//                    }
//                    cartLimitCount = Integer.parseInt((String) hashMap.get("appValue"));
//                }
//            }
//
//        }
        if (cartLimitCount != 0 && qty > cartLimitCount) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_LIMIT_ADD);
        }
        return qty;
    }

    private void checkStocks(BaseAddGoodsBO baseRequestDTO, CheckBussinessRulesBO checkBussinessRulesBO){

        ProductBO product = checkBussinessRulesBO.getProduct();
        boolean isLimit =false;
        if (product.getType() == ProductType.NOSPEC.getCode()
                && product.getStockLimit() == 1) {
            isLimit = true;
        } else {
            for (ProductBO.SkuProductBean skuProductBean : product.getSkuList()) {
                if (baseRequestDTO.getSkuId().equals(skuProductBean.getSkuId()) && skuProductBean.getStockLimit() == 1) {
                    isLimit = true;
                    break;
                }
            }
        }
        if (!isLimit){
            return;
        }
        List<CartGoods> oldCartGoodsList = checkBussinessRulesBO.getCartGoods();
        CartGoods cartGoods = baseRequestDTO.getAddGoods();
        int qty;
        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();
                }
            }
        }

        GetProductStock getProductStock = new GetProductStock();
        getProductStock.setChannel(BusinessTypeEnum.getByType(baseRequestDTO.getMenuType()).getCode());
        getProductStock.setPartnerId(baseRequestDTO.getPartnerId());
        getProductStock.setStoreId(baseRequestDTO.getShopId());
        List<Long> productIds = new ArrayList<>();
        productIds.add(Long.parseLong(checkBussinessRulesBO.getProduct().getGoodsId()));
        getProductStock.setProductIds(productIds);

        // 查询库存
        List<ProductStockBO> productStock = productManager.getProductStock(getProductStock, baseRequestDTO.getManagerService().getProductService());
        ProductStockBO availableStocks = null;
        if (CollectionUtils.isNotEmpty(productStock)){
            availableStocks = productStock.get(0);
        }
        int stock = availableStocks == null || availableStocks.getQty() == null ? 0 : availableStocks.getQty();
        if (stock <= 0) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_STOCK_NOT_HAVE);
        } else if (stock < qty) {
            throw new BizServiceException(ResponseResult.SHOPPING_CART_STOCK_NOT_HAVE, "仅剩" + stock + "件库存了");
        }

    }


    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);
                }
            }
        }
    }

}
