package cn.freemud.service.impl.calculate;

import cn.freemud.base.entity.BaseResponse;
import cn.freemud.constant.ShoppingCartConstant;
import cn.freemud.demo.entities.bo.goods.CalculationDiscountBO;
import cn.freemud.demo.entities.bo.goods.ShoppingCartApportionBO;
import cn.freemud.entities.dto.GetPaidRuleRequestDto;
import cn.freemud.entities.dto.GetPaidRuleResponseDto;
import cn.freemud.entities.dto.activity.ActivityDiscountsDto;
import cn.freemud.entities.dto.calculate.*;
import cn.freemud.entities.dto.order.PackAmountConfig;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.CartGoods;
import cn.freemud.entities.vo.ShoppingCartGoodsResponseVo;
import cn.freemud.entities.vo.ShoppingCartInfoRequestVo;
import cn.freemud.enums.*;
import cn.freemud.handle.CommonFunctionHandle;
import cn.freemud.service.thirdparty.CustomerApplicationClient;
import cn.freemud.utils.BeanUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import ma.glasnost.orika.MapperFacade;
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.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.freemud.constant.ShoppingCartConstant.SHOPPING_CART_EMPTY_GOODS_LIST;
import static cn.freemud.constant.ShoppingCartConstant.SHOPPING_CART_INVALIAD_GOODS;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: cn.freemud.service.impl.calculate CalculationCommonService
 * @Description: TDO 描述....
 * @author: family
 * @date: 2020/9/14
 * @Copyright: www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
public class CalculationCommonService {

    /**
     * coco商户
     */
    @Value("#{'${coco.partnerId}'.split(',')}")
    private List<String> cocoPartnerId;

    @Autowired
    private CustomerApplicationClient customerApplicationClient;

    @Resource
    private MapperFacade mapperFacade;

    @Autowired
    private CommonFunctionHandle commonFunctionHandle;

    /**
     * 初始化价格  新算价走了
     */
    public void initShoppingCart(CalculationDiscountResult discountResult
            , List<CartGoods> cartGoodsList
            , ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo,
                                 String couponCode,
                                 ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {

        /**
         * 使用促销算价赋值行记录
         */
        List<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;

            this.rowRealAmount(goods, cartGoods, couponCode);

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

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

            //包装费行记录
            packageAmount = cartGoods.getPackPrice() * cartGoods.getQty();
            cartGoods.setPackPrice(packageAmount);
            totalPackageAmount += packageAmount;
        }
        shoppingCartGoodsResponseVo.setOriginalTotalAmount(discountResult == null ? totalOriginalAmount : discountResult.getOriginalTotalAmount());
        shoppingCartGoodsResponseVo.setTotalAmount(discountResult == null ? totalAmount : discountResult.getTotalAmount());
        // fisherman 目前需求: 是否满足配送 按照商品原价|现价匹配
        shoppingCartGoodsResponseVo.setShoppingCartGoodsAmount(shoppingCartGoodsResponseVo.getTotalAmount());
        shoppingCartGoodsResponseVo.setShoppingCartOriginalGoodsAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount());
        //fisherman 【ID1033456】自提根据模板配置计算餐具包装费 新算价一起处理
        PackAmountConfig packAmountByStoreConfig = commonFunctionHandle.getPackAmountByStoreConfig(shoppingCartInfoRequestVo, totalPackageAmount, shoppingCartGoodsResponseVo.getTotalAmount());
        shoppingCartGoodsResponseVo.setNewPackAmount(packAmountByStoreConfig.getNewPackAmount());
        shoppingCartGoodsResponseVo.setPackageAmountCollectType(CollectionUtils.isEmpty(packAmountByStoreConfig.getCollectType()) ? 1 : 2);
        // fisehrman 总优惠金额 需要+配送券的优惠金额
        if (discountResult == null) {
            shoppingCartGoodsResponseVo.setTotalDiscountAmount(0L);
        } else {
            // 需要算上配送券的优惠金额
            Integer discountAmount = 0;
            if (CollectionUtils.isNotEmpty(discountResult.getDiscounts())) {
                // 过滤出配送券金额 和 满减配送费活动金额
                double sum = discountResult.getDiscounts().stream()
                        .filter(c -> c.getType() != null && (c.getType().compareTo(ActivityTypeEnum.TYPE_34.getCode()) == 0 || c.getType().compareTo(ActivityTypeEnum.TYPE_14.getCode()) == 0))
                        .mapToDouble(Discount::getDiscount)
                        .sum();
                discountAmount = Double.valueOf(sum).intValue();
            }
            shoppingCartGoodsResponseVo.setTotalDiscountAmount(discountResult.getTotalDiscountAmount() + discountAmount);
        }
    }

    private void rowRealAmount(List<Goods> goods, CartGoods cartGoods, String couponCode) {
        // 防止前置 goods 空指针
        if (CollectionUtils.isEmpty(goods)) {
            return;
        }
        Goods find = goods
                .stream().filter((k) -> Objects.equals(k.getCartGoodsUid(), cartGoods.getCartGoodsUid()))
                .findFirst().orElse(null);

        if (find == null) return;
        cartGoods.setAmount(find.getRealAmount());
        cartGoods.setCurrentCouponDiscount(0);
        cartGoods.setFinalPrice(find.getNowPrice());
        if (CollectionUtils.isNotEmpty(find.getDiscounts())) {
//            ActivityCalculationDiscountResponseDto.CalculationDiscountResult.Goods.GoodsDiscount goodsDiscount = find.getDiscounts().stream()
//                    .filter(p -> p.getActivityCode().equals(couponCode)).findFirst().orElse(null);
//            if (goodsDiscount != null){
//            }
            for (GoodsDiscount goodsDiscount : find.getDiscounts()) {
                if (goodsDiscount.getActivityCode().equals(couponCode)) {
                    cartGoods.setCurrentCouponDiscount(goodsDiscount.getDiscount() == null ? 0 : goodsDiscount.getDiscount().intValue());
                }
                if (StringUtils.isNotEmpty(goodsDiscount.getCurrentMembershipLevel())) {
                    cartGoods.setCurrentMemberLevel(goodsDiscount.getCurrentMembershipLevel());
                }
            }
        }
        //cartGoods.setOriginalAmount(find.getOriginalPrice());
        /**
         * 套餐的原价   fisherman ---> 可能历史原因 促销给的 originalPrice 没有包含可选搭配的价格, 所以购物车自己又重新算了一遍
         * 20211015 进行 【盛香亭】【B端】订单明细套餐商品价格计算 需求,  促销会根据商户配置 设置套餐的划线价, 这里直接取促销的值就可以了 + 购物车自己算可算搭配的值
         */
        Long originPrice = find.getOriginalPrice();
//        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, SmallMaterial> gChoices = find.getSmallMaterial()
                    .stream().filter(d -> type2.equals(d.getType()))
                    .collect(Collectors.toMap(SmallMaterial::getGoodsId, Function.identity(), (k1, k2) -> k1));
            long amount = 0L;

            //可选搭配
            for (CartGoods.ComboxGoods choice : cartGoods.getProductGroupList()) {
                SmallMaterial mt = gChoices.get(choice.getGoodsId());
                if (mt == null) {
                    amount += choice.getAmount() * choice.getQty();
                } else {
                    amount += mt.getRealAmount();
                    choice.setCurrentCouponDiscount(0);
                    if (CollectionUtils.isNotEmpty(mt.getDiscounts())) {
                        GoodsDiscount goodsDiscount = mt.getDiscounts().stream()
                                .filter(p -> p.getActivityCode().equals(couponCode)).findFirst().orElse(null);
                        if (goodsDiscount != null) {
                            choice.setCurrentCouponDiscount(goodsDiscount.getDiscount() == null ? 0 : goodsDiscount.getDiscount().intValue());
                        }
                    }
                    choice.setAmount(mt.getRealAmount().longValue());
                }
                originPrice += choice.getFinalPrice() * choice.getQty();
            }
            cartGoods.setAmount(cartGoods.getAmount() + amount);
        }
        /**
         * 小料
         */
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            Integer type1 = 1;
            Map<String, SmallMaterial> sChoices = find.getSmallMaterial()
                    .stream().filter(d -> type1.equals(d.getType()))
                    .collect(Collectors.toMap(SmallMaterial::getGoodsId, Function.identity(), (k1, k2) -> k1));

            for (CartGoods.MaterialGoods mg : cartGoods.getProductMaterialList()) {
                SmallMaterial sm = sChoices.get(mg.getSpuId());
                if (sm != null) {
                    mg.setCurrentCouponDiscount(0);
                    if (CollectionUtils.isNotEmpty(sm.getDiscounts())) {
                        GoodsDiscount goodsDiscount = sm.getDiscounts().stream()
                                .filter(p -> p.getActivityCode().equals(couponCode)).findFirst().orElse(null);
                        if (goodsDiscount != null) {
                            mg.setCurrentCouponDiscount(goodsDiscount.getDiscount() == null ? 0 : goodsDiscount.getDiscount().intValue());
                        }
                    }
                    mg.setAmount(sm.getRealAmount().longValue());
                }

                mg.setQty(mg.getQty() * cartGoods.getQty());
                mg.setOriginalAmount(mg.getFinalPrice() * mg.getQty());
            }
        }
        if (GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType().equals(cartGoods.getGoodsType())) {
            cartGoods.setOriginalAmount(originPrice);
//            cartGoods.setOriginalPrice(find.getOriginalPrice());
            // fisherman  取值 originPrice 的原因是因为 如果存在可选搭配, 促销反馈的价格是没计算可选搭配的, 所以这里需要加上去,
            cartGoods.setOriginalPrice(originPrice);
        }

    }

    /**
     * 设置行记录享受的优惠及总优惠
     *
     * @param cartGoods
     * @return
     */
    public ShoppingCartGoodsDto.CartGoodsDetailDto convertCartGoods2DetailGoodsList(Goods calculationGoods
            , CartGoods cartGoods
            , String partnerId) {
        ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto = this.convertCartGoods2DetailGoods(calculationGoods, cartGoods, partnerId);
        return cartGoodsDetailDto;
    }


    /**
     * 设置行记录享受的优惠及总优惠
     *
     * @param cartGoods
     * @return
     */
    public ShoppingCartApportionBO.CartGoodsDetailDto convertCartGoods2NewDetailGoodsList(CalculationDiscountBO.CalculationDiscountResult.Goods calculationGoods
            , CartGoods cartGoods, String partnerId) {

        Goods oldGoods = mapperFacade.map(calculationGoods, Goods.class);

        ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto = this.convertCartGoods2DetailGoods(oldGoods, cartGoods, partnerId);

        ShoppingCartApportionBO.CartGoodsDetailDto newDetail = mapperFacade.map(cartGoodsDetailDto, ShoppingCartApportionBO.CartGoodsDetailDto.class);
        return newDetail;
    }

    /**
     * 组装添加商品和更新商品和查询的响应信息
     * <p>
     * 查询购物车计算包装费
     *
     * @param cartGoodsList
     * @param shoppingCartGoodsResponseVo
     * @param opt
     * @param shoppingCartInfoRequestVo
     */
    public void setAddAndUpdateResponse(List<CartGoods> cartGoodsList
            , ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo
            , ShoppingCartInfoRequestVo shoppingCartInfoRequestVo
            , String opt) {
        shoppingCartGoodsResponseVo.setVersion(2);
        shoppingCartGoodsResponseVo.setProducts(cartGoodsList);
        shoppingCartGoodsResponseVo.setProductsCount(cartGoodsList.size());
        String toastMsg = shoppingCartGoodsResponseVo.getToastMsg();
        if (StringUtils.isNotEmpty(toastMsg)) {
            toastMsg = shoppingCartInfoRequestVo != null && ObjectUtils.equals(SubmitPageEnum.YES.getCode(), shoppingCartInfoRequestVo.getFlag()) ? SHOPPING_CART_EMPTY_GOODS_LIST : SHOPPING_CART_INVALIAD_GOODS;
            setToastMsgIfNotExist(shoppingCartGoodsResponseVo, toastMsg);
            //结算页，只有商品全部非法（即products为空）时，才提示changed为true toastMsg 不为空
            // 请求里面的  enableSharing = 0 并且  changed = true
            boolean changed = shoppingCartInfoRequestVo != null
                    &&shoppingCartInfoRequestVo.getEnableSharing() != null
                    && shoppingCartInfoRequestVo.getEnableSharing().compareTo(0) == 0
                    && Objects.nonNull(shoppingCartGoodsResponseVo.getChanged())
                    && shoppingCartGoodsResponseVo.getChanged().compareTo(true) == 0;
            if (changed) {
                shoppingCartGoodsResponseVo.setChanged(true);
                shoppingCartGoodsResponseVo.setToastMsg("购物车数据异常,需要重新请求购物车list接口");
            } else {
                shoppingCartGoodsResponseVo.setChanged(CollectionUtils.isEmpty(cartGoodsList));
                shoppingCartGoodsResponseVo.setToastMsg(CollectionUtils.isEmpty(cartGoodsList) ? toastMsg : "");
            }
        }
        // 更新和添加商品时不需要包装费
        if (ShoppingCartConstant.ADD_AND_UPDATE.equals(opt)) {
            shoppingCartGoodsResponseVo.setNewPackAmount(null);
            return;
        }
        //==========================  购物车查询特有逻辑  =================================
        // 到店自取包装费设为null,外卖要计算包装费，flag为1表示去结算
        // 兼容老版本判断null
        if (Objects.equals(shoppingCartInfoRequestVo.getOrderType(), CreateOrderType.COLLECT_GOODS.getCode())
                && (Objects.equals(shoppingCartInfoRequestVo.getReachStoreType(), null)
                || Objects.equals(shoppingCartInfoRequestVo.getReachStoreType(), OrderType.EAT_IN.getCode()))) {
            shoppingCartGoodsResponseVo.setNewPackAmount(null);
        } else if ((Objects.equals(shoppingCartInfoRequestVo.getOrderType(), CreateOrderType.TAKE_OUT.getCode())
                || Objects.equals(shoppingCartInfoRequestVo.getReachStoreType(), OrderType.COLLECT_GOODS.getCode()))
                && Objects.equals(shoppingCartInfoRequestVo.getFlag(), SubmitPageEnum.YES.getCode())) {
            Long packAmount = shoppingCartGoodsResponseVo.getNewPackAmount() == null ? 0 : shoppingCartGoodsResponseVo.getNewPackAmount();
            Long originalTotalAmount = shoppingCartGoodsResponseVo.getOriginalTotalAmount() + packAmount;
            Long totalAmount = shoppingCartGoodsResponseVo.getTotalAmount() + packAmount;
            shoppingCartGoodsResponseVo.setOriginalTotalAmount(originalTotalAmount);
            shoppingCartGoodsResponseVo.setTotalAmount(totalAmount);
        }
    }

    /**
     * 在原价、现价、折扣价上增加第一次使用会员卡的费用
     *
     * @param shoppingCartInfoRequestVo
     * @param shoppingCartGoodsResponseVo
     */
    public void addNeedCardAmount(ShoppingCartInfoRequestVo shoppingCartInfoRequestVo, ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo) {
        ShoppingCartInfoRequestVo.BuyMemberCard buyMemberCard = shoppingCartInfoRequestVo.getBuyMemberCard();
        if (shoppingCartInfoRequestVo.getBuyMemberCard() == null || StringUtils.isEmpty(buyMemberCard.getPaidId()) || StringUtils.isEmpty(buyMemberCard.getRuleId())) {
            return;
        }
        GetPaidRuleRequestDto getPaidRuleRequestDto = new GetPaidRuleRequestDto();
        getPaidRuleRequestDto.setPartnerId(shoppingCartInfoRequestVo.getPartnerId());
        getPaidRuleRequestDto.setPaidId(buyMemberCard.getPaidId());
        getPaidRuleRequestDto.setRuleId(buyMemberCard.getRuleId());
        BaseResponse<GetPaidRuleResponseDto> baseResponse = customerApplicationClient.getPaidRule(getPaidRuleRequestDto);
        if (baseResponse == null || !ResponseResult.SUCCESS.getCode().equals(baseResponse.getCode()) || baseResponse.getResult() == null
                || baseResponse.getResult().getActivityPrice() == null) {
            return;
        }
        // 购买会员卡的金额
        Integer activityPrice = baseResponse.getResult().getActivityPrice();
        // 首次使用会员卡享受的折扣金额
        Integer firstCouponAmount = baseResponse.getResult().getFirstCouponAmount() == null ? 0 : baseResponse.getResult().getFirstCouponAmount();
        Long originalTotalAmount = shoppingCartGoodsResponseVo.getOriginalTotalAmount() + activityPrice;
        Long totalAmount = shoppingCartGoodsResponseVo.getTotalAmount() + (activityPrice - firstCouponAmount);
        Long totalDiscountAmount = shoppingCartGoodsResponseVo.getTotalDiscountAmount() + firstCouponAmount;
        shoppingCartGoodsResponseVo.setOriginalTotalAmount(originalTotalAmount);
        shoppingCartGoodsResponseVo.setTotalAmount(totalAmount);
        shoppingCartGoodsResponseVo.setTotalDiscountAmount(totalDiscountAmount);
        shoppingCartGoodsResponseVo.setCardOriginalAmount(activityPrice);
        shoppingCartGoodsResponseVo.setCardDiscountAmount(firstCouponAmount);
    }

    /**
     * 计算第一次使用会员卡需多支付的金额  单位:分
     *
     * @param shoppingCartInfoRequestVo
     * @param shoppingCartGoodsDto
     * @return
     */
    public void getNeedCardAmount(ShoppingCartInfoRequestVo shoppingCartInfoRequestVo, ShoppingCartGoodsDto shoppingCartGoodsDto) {
        ShoppingCartInfoRequestVo.BuyMemberCard buyMemberCard = shoppingCartInfoRequestVo.getBuyMemberCard();
        if (buyMemberCard != null && StringUtils.isNotEmpty(buyMemberCard.getPaidId()) && StringUtils.isNotEmpty(buyMemberCard.getRuleId())) {
            GetPaidRuleRequestDto getPaidRuleRequestDto = new GetPaidRuleRequestDto();
            getPaidRuleRequestDto.setPartnerId(shoppingCartInfoRequestVo.getPartnerId());
            getPaidRuleRequestDto.setPaidId(buyMemberCard.getPaidId());
            getPaidRuleRequestDto.setRuleId(buyMemberCard.getRuleId());
            BaseResponse<GetPaidRuleResponseDto> baseResponse = customerApplicationClient.getPaidRule(getPaidRuleRequestDto);
            if (baseResponse == null || baseResponse.getResult() == null || !ResponseResult.SUCCESS.getCode().equals(baseResponse.getCode())
                    || baseResponse.getResult().getActivityPrice() == null) {
                return;
            }
            Integer activityPrice = baseResponse.getResult().getActivityPrice();
            Integer firstCouponAmount = baseResponse.getResult().getFirstCouponAmount() == null ? 0 : baseResponse.getResult().getFirstCouponAmount();
            Integer needCardAmount = activityPrice - firstCouponAmount;
            shoppingCartGoodsDto.setMemberCardAmount(needCardAmount);
            shoppingCartGoodsDto.setCardOriginalAmount(baseResponse.getResult().getActivityPrice());
            shoppingCartGoodsDto.setCardDiscountAmount(firstCouponAmount);
            shoppingCartGoodsDto.setOriginalTotalAmount(shoppingCartGoodsDto.getOriginalTotalAmount() + activityPrice);
            shoppingCartGoodsDto.setTotalAmount(shoppingCartGoodsDto.getTotalAmount() + needCardAmount);
            shoppingCartGoodsDto.setTotalDiscountAmount(shoppingCartGoodsDto.getTotalDiscountAmount() + firstCouponAmount);
        }
    }

    /**
     * 当ToastMsg为空时才赋值
     *
     * @param shoppingCartGoodsResponseVo
     * @param message
     */
    private void setToastMsgIfNotExist(ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo, String message) {
        if (StringUtils.isEmpty(shoppingCartGoodsResponseVo.getToastMsg())) {
            shoppingCartGoodsResponseVo.setToastMsg(message);
        }
    }

    /**
     * 给订单商品设置基础信息
     * - 普通商品
     * - 固定套餐
     * - 加料商品
     * - 加价购单独处理
     * - 赠品单独处理
     *
     * @param cartGoods
     * @param calculationGoods
     */
    private ShoppingCartGoodsDto.CartGoodsDetailDto convertCartGoods2DetailGoods(Goods calculationGoods
            , CartGoods cartGoods
            , String partnerId) {

        ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto = new ShoppingCartGoodsDto.CartGoodsDetailDto();
        cartGoodsDetailDto.setCartGoodsUid(cartGoods.getCartGoodsUid());
        // fisherman
        cartGoodsDetailDto.setOriginalProductType(cartGoods.getOriginalProductType());
        cartGoodsDetailDto.setLinkedId(cartGoods.getLinkedId());
        cartGoodsDetailDto.setTaxId(cartGoods.getTaxId());
        cartGoodsDetailDto.setTax(cartGoods.getTax());
        cartGoodsDetailDto.setSpuId(cartGoods.getSpuId());
        cartGoodsDetailDto.setSpuName(cartGoods.getSpuName());
        cartGoodsDetailDto.setSpuForeignName(cartGoods.getSpuForeignName());
        cartGoodsDetailDto.setSkuId(StringUtils.isEmpty(cartGoods.getSkuId()) ? cartGoods.getSpuId() : cartGoods.getSkuId());
        cartGoodsDetailDto.setSkuName(StringUtils.isEmpty(cartGoods.getSkuName()) ? cartGoods.getSpuName() : cartGoods.getSkuName());
        cartGoodsDetailDto.setSkuForeignName(StringUtils.isEmpty(cartGoods.getSkuForeignName()) ? cartGoods.getSpuForeignName() : cartGoods.getSkuForeignName());
        cartGoodsDetailDto.setIsSendGoods(false);
        if (calculationGoods != null) {
            // 修复购物车NPE 是否为赠品
            cartGoodsDetailDto.setIsSendGoods(ObjectUtils.equals(1, calculationGoods.getCartGoodType()));
        }
        cartGoodsDetailDto.setOriginalPrice(cartGoods.getOriginalPrice());
        cartGoodsDetailDto.setSalePrice(cartGoods.getOriginalPrice());
        cartGoodsDetailDto.setPicture(cartGoods.getPic());
        cartGoodsDetailDto.setQty(cartGoods.getQty());
        cartGoodsDetailDto.setActivityType(cartGoods.getActivityType());
        cartGoodsDetailDto.setNodeId(cartGoods.getNodeId());
        cartGoodsDetailDto.setCategoryName(cartGoods.getCategoryName());
        cartGoodsDetailDto.setCouponCode(cartGoods.getCouponCode());
        cartGoodsDetailDto.setStockLimit(cartGoods.isStockLimit());
        cartGoodsDetailDto.setProductCode(cartGoods.getCustomerCode());
        cartGoodsDetailDto.setCustomerCode(cartGoods.getCustomerCode());
        cartGoodsDetailDto.setWeight(cartGoods.getWeight());
        cartGoodsDetailDto.setUnit(cartGoods.getUnit());
        cartGoodsDetailDto.setActivityDiscountsDtos(new ArrayList<>());
        cartGoodsDetailDto.setClassificationId(cartGoods.getClassificationId());
        cartGoodsDetailDto.setClassificationName(cartGoods.getClassificationName());
        if (cartGoods.isWeightType()) {
            cartGoodsDetailDto.setProductType(ProductType.WEIGHT_PRODUCT.getCode());
        }
        if (calculationGoods != null) {
            cartGoodsDetailDto.setOriginalPrice(calculationGoods.getOriginalPrice());
        } else {
            cartGoodsDetailDto.setOriginalPrice(cartGoods.getOriginalPrice());
        }
        if (calculationGoods != null) {
            if (cartGoodsDetailDto.getIsSendGoods()) {
                // 由于买赠活动中，赠品有属性的时候会裂为多行，所有优惠金额不能直接用促销返回的， 需要根据实际购物车行中的数量来计算
                int discountAmt = calculationGoods.getDiscountAmount().intValue();
                int discountCount = calculationGoods.getGoodsQuantity();
                cartGoodsDetailDto.setTotalDiscountAmount(discountAmt / discountCount * cartGoods.getQty());
            } else {
                cartGoodsDetailDto.setTotalDiscountAmount(calculationGoods.getDiscountAmount().intValue());
            }
        } else {
            cartGoodsDetailDto.setTotalDiscountAmount(cartGoods.getOriginalAmount().intValue() - cartGoods.getAmount().intValue());
        }
        //设置行优惠
        List<ActivityDiscountsDto> activityDiscountsDtoList = new ArrayList<>();
        if (null != calculationGoods) {
            if (CollectionUtils.isNotEmpty(calculationGoods.getDiscounts())){
                for (GoodsDiscount discount : calculationGoods.getDiscounts()) {
                    ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
                    activityDiscountsDto.setActivityCode(discount.getActivityCode());
                    activityDiscountsDto.setActivityName(this.convertName(discount.getType(), discount.getActivityName()));
                    activityDiscountsDto.setActivityType(this.convertType(discount.getType()));
                    if (cartGoodsDetailDto.getIsSendGoods()) {
                        // 这里不直接取促销返回的discount是因为如果是赠品的情况下， 如果赠品有属性，会进行拆行
                        // 例如：赠品*2， 会被拆为 2个 赠品*1， 每个赠品都可以选不同属性， 这样赠品的优惠信息需要将优惠金额也要拆到每一行上去
                        activityDiscountsDto.setDiscountAmount(discount.getDiscount().intValue() / discount.getActualGoodsNumber() * cartGoods.getQty());
                        activityDiscountsDto.setActualActivityGoodsNumber(1);
                    } else {
                        // 这里不直接取促销返回的discount是因为如果是赠品的情况下， 如果赠品有属性，会进行拆行
                        // 例如：赠品*2， 会被拆为 2个 赠品*1， 每个赠品都可以选不同属性， 这样赠品的优惠信息需要将优惠金额也要拆到每一行上去
                        activityDiscountsDto.setDiscountAmount(discount.getDiscount().intValue());
                        activityDiscountsDto.setActualActivityGoodsNumber(discount.getActualGoodsNumber());
                    }
                    activityDiscountsDtoList.add(activityDiscountsDto);
                }
            } else if (CollectionUtils.isNotEmpty(calculationGoods.getSmallMaterial())) {
                // fix 若套餐无固定搭配， 促销返回的均摊在父商品上是空的，这时需要把子商品的优惠放到父商品里
                Map<Integer, ActivityDiscountsDto> map = new HashMap<>();
                calculationGoods.getSmallMaterial().forEach(sm -> {
                    if (CollectionUtils.isNotEmpty(sm.getDiscounts())) {
                        sm.getDiscounts().forEach(discount -> {
                            Integer type = this.convertType(discount.getType());
                            ActivityDiscountsDto dto = map.getOrDefault(type, new ActivityDiscountsDto());
                            dto.setActivityCode(discount.getActivityCode());
                            dto.setActivityName(this.convertName(discount.getType(), discount.getActivityName()));
                            dto.setActivityType(this.convertType(discount.getType()));
                            dto.setDiscountAmount(Optional.ofNullable(dto.getDiscountAmount()).orElse(0) + discount.getDiscount().intValue());
                            dto.setActualActivityGoodsNumber(Optional.ofNullable(dto.getActualActivityGoodsNumber()).orElse(0) + discount.getActualGoodsNumber());
                            map.put(type, dto);
                        });
                    }
                });
                //存到商品优惠里
                map.forEach((type, dto) -> {
                    activityDiscountsDtoList.add(dto);
                });
            }
        }
        cartGoodsDetailDto.setActivityDiscountsDtos(activityDiscountsDtoList);

        /**
         * 加料商品
         */
        if (CollectionUtils.isNotEmpty(cartGoods.getProductMaterialList())) {
            List<ShoppingCartGoodsDto.CartGoodsDetailDto.MaterialGoods> materialList = new ArrayList<>();
            HashMap<String, BlockRow> smallRow = this.drawnSmallAndGroupRow(calculationGoods, 1, false);
            for (CartGoods.MaterialGoods mg : cartGoods.getProductMaterialList()) {
                ShoppingCartGoodsDto.CartGoodsDetailDto.MaterialGoods goods = new ShoppingCartGoodsDto.CartGoodsDetailDto.MaterialGoods();
                goods.setSpuId(mg.getSpuId());
                goods.setSpuName(mg.getSpuName());
                goods.setSpuForeignName(mg.getSpuForeignName());
                goods.setSalePrice(mg.getFinalPrice());
                goods.setQty(mg.getQty());
                goods.setCustomerCode(mg.getCustomerCode());
                goods.setOriginalPrice(mg.getOriginalPrice());
                //提前当前行促销
                BlockRow blockRow = smallRow.get(goods.getSpuId());
                List<ActivityDiscountsDto> activityDiscountsDtos = new ArrayList<>();
                if (null == blockRow) {
                    goods.setTotalDiscountAmount(mg.getOriginalAmount().intValue() - mg.getAmount().intValue());
                    goods.setActivityDiscountsDtos(activityDiscountsDtos);
                } else {
                    goods.setTotalDiscountAmount(blockRow.getDiscountAmount());
                    List<ActivityDiscountsDto> smDiscount = this.drawSmallDiscount(blockRow.getDiscounts());
                    goods.setActivityDiscountsDtos(smDiscount);
                }
                goods.setOriginalProductType(mg.getOriginalProductType());
                materialList.add(goods);
                cartGoodsDetailDto.setOriginalPrice(cartGoodsDetailDto.getOriginalPrice() + goods.getOriginalPrice() * (goods.getQty() / cartGoodsDetailDto.getQty()));
                cartGoodsDetailDto.setTotalDiscountAmount(cartGoodsDetailDto.getTotalDiscountAmount() + goods.getTotalDiscountAmount());
            }
            cartGoodsDetailDto.setProductType(ProductType.MATERIAL.getCode());
            cartGoodsDetailDto.setMaterialList(materialList);
        }
        /**
         * 固定搭配
         * productComboList
         * fisherman 固定搭配套餐价设置,促销不计算可选搭配价格
         */
        Long originalPriceSum = 0L;
        List<ShoppingCartGoodsDto.CartGoodsDetailDto> combs = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(cartGoods.getProductComboList())) {
            HashMap<String, BlockRow> gxDiscount = this.drawnSmallAndGroupRow(calculationGoods, 2, true);
            List<ShoppingCartGoodsDto.CartGoodsDetailDto> comboLists = this.com2DetailGoods(gxDiscount, cartGoods.getProductComboList(), cartGoods, true);
            combs.addAll(comboLists);
            cartGoodsDetailDto.setProductType(ProductType.SETMEAL.getCode());
            if (calculationGoods != null) {
                originalPriceSum = calculationGoods.getOriginalPrice();
            } else {
                for (ShoppingCartGoodsDto.CartGoodsDetailDto comboList : comboLists) {
                    originalPriceSum += (comboList.getQty() / cartGoods.getQty()) * comboList.getOriginalPrice();
                }
            }
            cartGoodsDetailDto.setOriginalPrice(originalPriceSum);
        }


        /**
         * 可选商品
         * productGroupList
         */
        if (CollectionUtils.isNotEmpty(cartGoods.getProductGroupList())) {
            HashMap<String, BlockRow> smDiscount = this.drawnSmallAndGroupRow(calculationGoods, 2, false);
            List<ShoppingCartGoodsDto.CartGoodsDetailDto> groupList = this.com2DetailGoods(smDiscount, cartGoods.getProductGroupList(), cartGoods, false);
            combs.addAll(groupList);
            int discountSum = groupList.stream().mapToInt(ShoppingCartGoodsDto.CartGoodsDetailDto::getTotalDiscountAmount).sum();
            cartGoodsDetailDto.setTotalDiscountAmount(cartGoodsDetailDto.getTotalDiscountAmount() + discountSum);
            originalPriceSum = 0L;
            for (ShoppingCartGoodsDto.CartGoodsDetailDto goodsDetailDto : groupList) {
                originalPriceSum += goodsDetailDto.getOriginalPrice() * (goodsDetailDto.getQty() / cartGoods.getQty());
                //originalPriceSum += goodsDetailDto.getOriginalPrice() * goodsDetailDto.getQty();
            }
            cartGoodsDetailDto.setProductType(ProductType.SETMEAL.getCode());
            cartGoodsDetailDto.setOriginalPrice(cartGoodsDetailDto.getOriginalPrice() + originalPriceSum);
        }
        cartGoodsDetailDto.setComboProducts(combs);
        List<ShoppingCartGoodsDto.CartGoodsDetailDto.CartGoodsExtra> cartGoodsExtras = BeanUtil.convertBeans(cartGoods.getExtra(), ShoppingCartGoodsDto.CartGoodsDetailDto.CartGoodsExtra::new);
        cartGoodsDetailDto.setExtraList(cartGoodsExtras);
        return cartGoodsDetailDto;
    }

    /**
     * 固定套餐+可选搭配转
     *
     * @param combo
     * @param cartGoods
     * @param isFixed
     */
    private List<ShoppingCartGoodsDto.CartGoodsDetailDto> com2DetailGoods(HashMap<String, BlockRow> discount
            , List<CartGoods.ComboxGoods> combo
            , CartGoods cartGoods, boolean isFixed) {

        List<ShoppingCartGoodsDto.CartGoodsDetailDto> combs = new ArrayList<>();
        for (CartGoods.ComboxGoods comb : combo) {
            ShoppingCartGoodsDto.CartGoodsDetailDto com = new ShoppingCartGoodsDto.CartGoodsDetailDto();
            com.setSpuId(comb.getGoodsId());
            com.setSpuName(comb.getSpuName());
            com.setLinkedId(comb.getLinkedId());
            com.setSpuForeignName(comb.getSpuForeignName());
            com.setSkuId(comb.getGoodsId());
            com.setSkuName(StringUtils.isEmpty(comb.getSkuName()) ? com.getSpuName() : com.getSkuName());
            com.setSkuForeignName(StringUtils.isEmpty(comb.getSkuForeignName()) ? com.getSpuForeignName() : com.getSkuForeignName());

            com.setPicture(comb.getPic());
            com.setProductType(comb.isWeightType() ? ProductType.WEIGHT_PRODUCT.getCode() : ProductType.SETMEAL.getCode());
            com.setParentProductId(cartGoods.getGoodsId());
            com.setIsFixedProduct(isFixed);
            com.setStockLimit(cartGoods.isStockLimit());
            com.setCustomerCode(comb.getCustomerCode());
            com.setWeight(comb.getWeight());
            com.setUnit(comb.getUnit());
            List<ShoppingCartGoodsDto.CartGoodsDetailDto.CartGoodsExtra> cartGoodsExtras = BeanUtil.convertBeans(comb.getExtra(), ShoppingCartGoodsDto.CartGoodsDetailDto.CartGoodsExtra::new);
            com.setExtraList(cartGoodsExtras);
            com.setQty(comb.getQty() * cartGoods.getQty());
            com.setOriginalPrice(comb.getFinalPrice());
            com.setOriginalProductType(comb.getOriginalProductType());
            //if (isFixed) {
            //    com.setOriginalPrice(comb.getFinalPrice());
            //    com.setQty(comb.getQty() * cartGoods.getQty());
            //} else {
            //    com.setQty(comb.getQty() * cartGoods.getQty());
            //    com.setOriginalPrice(comb.getFinalPrice());
            //}

            //todo
            BlockRow row = discount.get(comb.getGoodsId());
            if (row == null) {
                com.setTotalDiscountAmount(0);
            } else {
                com.setTotalDiscountAmount(row.getDiscountAmount());
            }
            combs.add(com);
        }
        return combs;
    }

    /**
     * 可选和小料
     *
     * @param discounts
     * @return
     */
    private List<ActivityDiscountsDto> drawSmallDiscount(List<Discounts> discounts) {
        List<ActivityDiscountsDto> activityDiscountsDto = new ArrayList<>();
        if (CollectionUtils.isEmpty(discounts)) return activityDiscountsDto;
        for (Discounts discount : discounts) {
            ActivityDiscountsDto dto = new ActivityDiscountsDto();
            dto.setActivityName(discount.getActivityName());
            dto.setActivityType(discount.getType());
            dto.setActivityCode(discount.getActivityCode());
            dto.setDiscountAmount(discount.getDiscount().intValue());
            activityDiscountsDto.add(dto);
        }
        return activityDiscountsDto;
    }

    /**
     * 提取促销行记录上的固定套餐和搭配
     *
     * @param goods
     * @param type
     * @param isFixed
     * @return
     */
    private HashMap<String, BlockRow> drawnSmallAndGroupRow(Goods goods
            , Integer type
            , Boolean isFixed) {

        HashMap<String, BlockRow> map = new HashMap<>();
        if (goods == null) return map;
        //固定搭配
        if (isFixed) {
            if (CollectionUtils.isNotEmpty(goods.getGroupCombox())) {
                for (GroupCombox gx : goods.getGroupCombox()) {
                    BlockRow blockRow = new BlockRow();
                    blockRow.setDiscountAmount(gx.getDiscountAmount());
                    blockRow.setGoodsId(gx.getGoodsId());
                    blockRow.setGoodsId(gx.getGoodsId());
                    blockRow.setGoodsQuantity(gx.getGoodsQuantity());
                    blockRow.setOriginalPrice(gx.getOriginalPrice());
                    blockRow.setRealAmount(gx.getRealAmount());
                    List<Discounts> discounts = new ArrayList<>();
                    if (CollectionUtils.isNotEmpty(gx.getDiscounts())) {
                        for (GoodsDiscount ds : gx.getDiscounts()) {
                            Discounts discount = new Discounts();
                            discount.setActivityCode(ds.getActivityCode());
                            discount.setActivityDesc(ds.getActivityDesc());
                            discount.setActivityName(ds.getActivityName());
                            discount.setActualGoodsNumber(ds.getActualGoodsNumber());
                            discount.setDiscount(ds.getDiscount());
                            discount.setGoodsId(ds.getGoodsId());
                            discount.setType(ds.getType());
                            discounts.add(discount);
                        }
                    }
                    blockRow.setDiscounts(discounts);
                    map.put(gx.getGoodsId(), blockRow);
                }
            }
        }
        //可选搭配及小料
        else {
            List<BlockRow> blockRows = new ArrayList<>();
            for (SmallMaterial sm : goods.getSmallMaterial()) {
                if (!type.equals(sm.getType())) continue;
                BlockRow blockRow = new BlockRow();
                blockRow.setDiscountAmount(sm.getDiscountAmount());
                blockRow.setGoodsId(sm.getGoodsId());
                blockRow.setGoodsId(sm.getGoodsId());
                blockRow.setGoodsQuantity(sm.getGoodsQuantity());
                blockRow.setOriginalPrice(sm.getOriginalPrice());
                blockRow.setRealAmount(sm.getRealAmount());
                List<Discounts> discounts = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(sm.getDiscounts())) {
                    for (GoodsDiscount ds : sm.getDiscounts()) {
                        Discounts discount = new Discounts();
                        discount.setActivityCode(ds.getActivityCode());
                        discount.setActivityDesc(ds.getActivityDesc());
                        discount.setActivityName(ds.getActivityName());
                        discount.setActualGoodsNumber(ds.getActualGoodsNumber());
                        discount.setDiscount(ds.getDiscount());
                        discount.setGoodsId(ds.getGoodsId());
                        discount.setType(ds.getType());
                        discounts.add(discount);
                    }
                }
                blockRow.setDiscounts(discounts);
                blockRows.add(blockRow);
                map.put(sm.getGoodsId(), blockRow);
            }
        }
        return map;
    }

    /**
     * 特价和套餐超出部分不在享受优惠提示
     */
    public void drawSurpassDiscountInfo(CalculationDiscountResult discountResult
            , ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo) {
        List<Integer> types = new ArrayList<>();
        types.add(ActivityTypeEnum.TYPE_2.getCode());
        types.add(ActivityTypeEnum.TYPE_1.getCode());
        if (discountResult == null || CollectionUtils.isEmpty(discountResult.getGoods())) return;

        List<Goods> goodsList = discountResult.getGoods()
                .stream()
                .filter(d -> CollectionUtils.isNotEmpty(d.getDiscounts()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(goodsList)) return;
        String toastMsg = "", uid = "";
        GoodsDiscount dis = null;
        for (Goods goods : goodsList) {
            dis = goods.getDiscounts()
                    .stream()
                    .filter(g -> types.contains(g.getType())).findFirst().orElse(null);
            if (null == dis) continue;
            if (goods.getGoodsQuantity() > dis.getActualGoodsNumber()) {
                //goods.get
                toastMsg = "该商品限" + dis.getActualGoodsNumber() + "份优惠 超出按照原价计算哦";
                uid = goods.getCartGoodsUid();
            }
        }
        if (StringUtils.isNotBlank(toastMsg)) {
            shoppingCartGoodsResponseVo.setToastMsg(toastMsg);
        }
        shoppingCartGoodsResponseVo.setUid(uid);
    }

    /**
     * @param type
     * @return
     */
    public Integer convertType(Integer type) {
        Integer newType = type;
        switch (type) {
            case 310:
                newType = 211;
                break;
            case 33:
                newType = 32;
                break;
            case 330:
                newType = 32;
                break;
        }
        return newType;
    }

    public String convertName(Integer type, String activityCode) {
        Integer newType = 310;
        String code = activityCode;
        if (newType.equals(type)) {
            code = "setMeal";
        }
        return code;
    }

    @Data
    @NoArgsConstructor
    public static class BlockRow {
        private Integer discountAmount;
        private List<Discounts> discounts;
        private String goodsId;
        private Integer goodsQuantity;
        private Integer originalPrice;
        private Integer realAmount;
        private Integer type;
    }

    @Data
    @NoArgsConstructor
    public static class Discounts {
        private String activityCode;
        private String activityDesc;
        private String activityName;
        private Integer actualGoodsNumber;
        private Long discount;
        private String goodsId;
        private Integer type;
    }
}