package cn.freemud.service.impl;

import cn.freemud.adapter.ShoppingCartConvertAdapter;
import cn.freemud.entities.dto.ActivityCalculationDiscountResponseDto;
import cn.freemud.entities.dto.UserLoginInfoDto;
import cn.freemud.entities.dto.activity.ActivityDiscountsDto;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.GoodsTypeEnum;
import cn.freemud.service.IPromotionService;
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;
import java.util.stream.Stream;

/**
 * All rights Reserved, Designed By www.freemud.com
 *
 * @version V1.0
 * @Title:
 * @Package: cn.freemud.service.impl
 * @Descripttion:
 * @author: shuhu.hou
 * @date: 2019/9/5
 * @Copyright: 2017 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目.
 */
@Service("setMealService")
public class SetMealServiceImpl implements IPromotionService {
    @Autowired
    private ShoppingCartConvertAdapter shoppingCartConvertAdapter;

    @Override
    public void updateShoppingCartGoodsDiscount(CouponPromotionVO couponPromotionVO, ActivityQueryDto activityQueryDto, ActivityCalculationDiscountResponseDto.CalculationDiscountResult calculationDiscountResult, List<CartGoods> cartGoodsList, ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo, UserLoginInfoDto userLoginInfoDto, ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {

        List<CartGoods> setMealProducts = cartGoodsList.stream().filter(cartGoods -> ObjectUtils.equals(GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType(), cartGoods.getGoodsType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(setMealProducts)) {
            return;
        }
        //套餐可选商品现价
        long productGroupTotalAmount = 0L;
        // 存储当前享受限时特价折扣的商品数量
        Map<String, Integer> numberMap = new HashMap<>();
        // 当前商品行现价
        Map<String, ActivityCalculationDiscountResponseDto.CalculationDiscountResult.Goods> goodsMap = calculationDiscountResult.getGoods().parallelStream()
                .collect(Collectors.toMap(ActivityCalculationDiscountResponseDto.CalculationDiscountResult.Goods::getGoodsId, Function.identity(), (k1, k2) -> k1));

        // 设置商品原价与商品现价的初始值
        for (CartGoods cartGoods : setMealProducts) {
            cartGoods.setOriginalAmount(cartGoods.getOriginalPrice() * cartGoods.getQty());
            cartGoods.setPackPrice(cartGoods.getPackPrice() * cartGoods.getQty());
            // 可选商品现总价
            long productGroupAmount = cartGoods.getProductGroupList().stream().mapToLong(t -> t.getFinalPrice() * t.getQty()).sum();
            productGroupTotalAmount += productGroupAmount * cartGoods.getQty();

            // 套餐（固定商品）现价
            String toastMsg = getTotalAmount(cartGoods, productGroupAmount, numberMap, goodsMap);
            if (StringUtils.isNotEmpty(toastMsg)) {
                shoppingCartGoodsResponseVo.setToastMsg(toastMsg);
                shoppingCartGoodsResponseVo.setUid(cartGoods.getCartGoodsUid());
            }

        }

        long totalFinalPrice = setMealProducts.stream().mapToLong(product -> product.getFinalPrice() * product.getQty()).sum();
        long totalOriginalPrice = setMealProducts.stream().mapToLong(product -> product.getOriginalPrice() * product.getQty()).sum();

        //总原价=促销优惠 - 套餐finalPrice + 套餐原价
        shoppingCartGoodsResponseVo.setOriginalTotalAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount() - totalFinalPrice + totalOriginalPrice);
        //总现价=促销现总价 + 可选商品现总价
        shoppingCartGoodsResponseVo.setTotalAmount(shoppingCartGoodsResponseVo.getTotalAmount() + productGroupTotalAmount);
        //总优惠=促销总优惠 + (套餐总原件 - 套餐总finalPrice - 可选商品总售价)
        shoppingCartGoodsResponseVo.setTotalDiscountAmount(shoppingCartGoodsResponseVo.getTotalDiscountAmount() + totalOriginalPrice - totalFinalPrice - productGroupTotalAmount);
    }

    @Override
    public void updateShoppingCartGoodsApportion(ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo, ActivityCalculationDiscountResponseDto.CalculationDiscountResult calculationDiscountResult, ShoppingCartGoodsDto shoppingCartGoodsDto, CreateOrderVo.PremiumExchangeActivity premiumExchangeActivity, ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {
        //套餐商品总优惠
        Integer totalDiscountAmount = 0;
        List<ShoppingCartGoodsDto.CartGoodsDetailDto> cartGoodsDetailDtos = shoppingCartGoodsDto.getProducts();
        List<ActivityCalculationDiscountResponseDto.CalculationDiscountResult.ApportionGoods> apportionGoods = calculationDiscountResult == null ? new ArrayList<>()
                : calculationDiscountResult.getApportionGoods();
        // key为：goodsId；value以逗号分割：0为goodsId分组对应的数量，value为已计算的折扣金额
        //此map是为了促销除不尽时，拆商品行所用，例如，3份折扣10元
        Map<String, String> duplicateGoodsMap = new HashMap<>();
        shoppingCartGoodsResponseVo.getProducts().stream().filter(product->ObjectUtils.equals(GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType(), product.getGoodsType())).collect(Collectors.groupingBy(CartGoods::getGoodsId, Collectors.counting())).forEach((goodsId, count) -> {
            duplicateGoodsMap.put(goodsId,String.format("%s,0", count));
        });
        // 套餐优惠明细
        for (CartGoods cartGoods : shoppingCartGoodsResponseVo.getProducts()) {
            if (ObjectUtils.equals(GoodsTypeEnum.SET_MEAL_GOODS.getGoodsType(), cartGoods.getGoodsType())) {
                // discountAmount=(套餐原价-套餐售价)*数量
                // productGroupDiscountAmount=可选商品现价总和
                // discountAmount-productGroupDiscountAmount:  当前商品行套餐商品总优惠= 套餐原总价-套餐现总价-套餐可选商品的现总价
                int discountAmount = (cartGoods.getOriginalPrice().intValue() - cartGoods.getFinalPrice().intValue()) * cartGoods.getQty();
                int productGroupDiscountAmount = cartGoods.getProductGroupList().stream().mapToInt(t -> t.getFinalPrice().intValue() * t.getQty()).sum();
                totalDiscountAmount += discountAmount - productGroupDiscountAmount * cartGoods.getQty();
                // 添加套餐父商品
                ShoppingCartGoodsDto.CartGoodsDetailDto parentCartGoods = shoppingCartConvertAdapter.convertCartGoods2DetailGoods(cartGoods, apportionGoods,duplicateGoodsMap);
                parentCartGoods.setTotalDiscountAmount(parentCartGoods.getTotalDiscountAmount()+ cartGoods.getOriginalAmount().intValue() - cartGoods.getAmount().intValue());
                parentCartGoods.getActivityDiscountsDtos().add(getActivityDiscountsDto(discountAmount - productGroupDiscountAmount * cartGoods.getQty()));
                // 添加套餐固定商品&可选商品: 做均摊
                parentCartGoods.setComboProducts(shoppingCartConvertAdapter.convertComboxGoods2DetailGoods(cartGoods,parentCartGoods.getTotalDiscountAmount()));
                cartGoodsDetailDtos.add(parentCartGoods);
            }
        }

        //订单级别，套餐优惠活动
        if (totalDiscountAmount > 0) {
            shoppingCartGoodsDto.getActivityDiscountsDtos().add(getActivityDiscountsDto(-totalDiscountAmount));
        }
    }

    private ActivityDiscountsDto getActivityDiscountsDto(Integer totalDiscountAmount) {
        ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
        activityDiscountsDto.setActivityCode("setMeal");
        activityDiscountsDto.setActivityName("套餐商品优惠");
        activityDiscountsDto.setActivityType(211);
        activityDiscountsDto.setDiscountAmount(totalDiscountAmount);
        return activityDiscountsDto;
    }

    /**
     * 促销活动有份数限制时，计算当前商品行总现价
     * 当超出份数限制，提示：该商品限 N 份优惠 超出按照原价计算哦
     *
     * @param cartGoods
     * @param productGroupAmount
     * @param numberMap
     * @param goodsMap
     * @return
     */
    private String getTotalAmount(CartGoods cartGoods, long productGroupAmount, Map<String, Integer> numberMap, Map<String, ActivityCalculationDiscountResponseDto.CalculationDiscountResult.Goods> goodsMap) {

        if (goodsMap.isEmpty()||goodsMap.get(cartGoods.getGoodsId()).getDiscountAmount() == 0) {
            cartGoods.setAmount((cartGoods.getFinalPrice() + productGroupAmount) * cartGoods.getQty());
            return "";
        }
        if (numberMap.get(cartGoods.getGoodsId()) == null) {
            int actualGoodsNumber = goodsMap.get(cartGoods.getGoodsId()).getDiscounts().stream().mapToInt(ActivityCalculationDiscountResponseDto.CalculationDiscountResult.Goods.GoodsDiscount::getActualGoodsNumber)
                    .min().orElse(goodsMap.get(cartGoods.getGoodsId()).getGoodsQuantity());
            numberMap.put(cartGoods.getGoodsId(), actualGoodsNumber);
        }
        // 可优惠数量
        Integer number = numberMap.get(cartGoods.getGoodsId());
        if (number > 0) {
            Long nowPrice = goodsMap.get(cartGoods.getGoodsId()).getNowPrice();
            //套餐固定商品价格
            long productComboxAmount = cartGoods.getQty() > number ? number * nowPrice + (cartGoods.getQty() - number) * cartGoods.getFinalPrice() : cartGoods.getQty() * nowPrice;
            cartGoods.setAmount(productComboxAmount + productGroupAmount * cartGoods.getQty());
            //设置剩余优惠数量
            numberMap.put(cartGoods.getGoodsId(), number - cartGoods.getQty());
            return number - cartGoods.getQty() < 0 ? "该商品限" + number + "份优惠 超出按照原价计算哦" : "";
        } else {
            cartGoods.setAmount((cartGoods.getFinalPrice() + productGroupAmount) * cartGoods.getQty());
            return "该商品限" + goodsMap.get(cartGoods.getGoodsId()).getDiscounts().get(0).getActualGoodsNumber() + "份优惠 超出按照原价计算哦";
        }
    }
}
