package cn.freemud.service.impl.calculate.promotion;

import cn.freemud.entities.dto.ActivityCalculationDiscountResponseDto;
import cn.freemud.entities.dto.ActivityResponseDto;
import cn.freemud.entities.dto.BenefitBeanDto;
import cn.freemud.entities.dto.PromotionMessageDto;
import cn.freemud.entities.dto.activity.ActivityQueryDto;
import cn.freemud.entities.dto.activity.ActivityQueryResponseDto;
import cn.freemud.entities.dto.calculate.CalculationSharingDiscountResponseDto;
import cn.freemud.entities.vo.ActivityList;
import cn.freemud.entities.vo.ActivityTip;
import cn.freemud.entities.vo.CartGoods;
import cn.freemud.entities.vo.ShoppingCartGoodsResponseVo;
import cn.freemud.enums.ActivityTypeEnum;
import cn.freemud.enums.GiftTypeEnum;
import cn.freemud.service.ActivityService;
import cn.freemud.utils.WebUtil;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.card.sdk.log.ApiLog;
import org.apache.commons.collections4.CollectionUtils;
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;

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

    @Autowired
    private ActivityService activityService;

    /**
     * 查询每满减和阶梯满减活动中的第一个，构建提示语，筛选出购物车内的参与满减的商品，计算总的优惠金额
     */
    public void fullResponse(CalculationSharingDiscountResponseDto.CalculationDiscountResult discountResult
            , List<CartGoods> cartGoodsList
            , ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo
            , ActivityQueryDto activityQueryDto) {


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

        if (discountResult == null || CollectionUtils.isEmpty(discountResult.getGoods())) {
            /**
             * 调用促销统一活动查询,过滤出参与的满减(目前只有每满减和阶梯满减)
             */
            activityTypeEnums.add(ActivityTypeEnum.TYPE_230);
            ActivityQueryResponseDto activityQueryResponseDto = activityService.queryActivityByType(activityQueryDto, activityTypeEnums, null);
            if (null==activityQueryResponseDto || CollectionUtils.isEmpty(activityQueryResponseDto.getResult())) {
                return;
            }
            Optional<ActivityResponseDto> first = activityQueryResponseDto.getResult().stream().findFirst();
            PromotionMessageDto promotionMessageDto = new PromotionMessageDto();
            ActivityResponseDto activityResponseDto = first.get();
            promotionMessageDto.setActivityId(activityResponseDto.getActivityCode());
            promotionMessageDto.setActivityName(activityResponseDto.getActivityName());
            promotionMessageDto.setActivityType(activityResponseDto.getActivityType());
            promotionMessageDto.setPromotionAmount(0L);

            StringBuilder messageBuilder = new StringBuilder();
            ArrayList<ActivityList> activityList = new ArrayList<>();

            List<BenefitBeanDto> benefitBeanDtos = activityResponseDto.getBenefits();
            BenefitBeanDto benefitBeanDto = benefitBeanDtos.get(0);
            //调用没有加入购物车的提示语的方法
            setMessageNotInShoppingCart(messageBuilder, activityResponseDto, benefitBeanDtos, benefitBeanDto, activityList);

            promotionMessageDto.setPromotionMessage(messageBuilder.toString());
            ActivityTip activityTip = new ActivityTip();
            activityTip.setActivityCode(promotionMessageDto.getActivityId());
            activityTip.setActivityType(promotionMessageDto.getActivityType());
            activityTip.setActivityName(promotionMessageDto.getPromotionMessage());
            activityTip.setActivityList(activityList);
            shoppingCartGoodsResponseVo.setActivityTip(activityTip);

            return;
        }

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

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

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

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

        /**
         * 调用促销统一活动查询,过滤出参与的满减(目前只有每满减和阶梯满减)
         */
        activityTypeEnums.add(ActivityTypeEnum.TYPE_230);
        ActivityQueryResponseDto activityQueryResponseDto = activityService.queryActivityByType(activityQueryDto, activityTypeEnums, null);
        if (null==activityQueryResponseDto || CollectionUtils.isEmpty(activityQueryResponseDto.getResult())) {
            return;
        }
        Optional<ActivityResponseDto> first = activityQueryResponseDto.getResult().stream().findFirst();
        PromotionMessageDto promotionMessageDto = new PromotionMessageDto();
        ActivityResponseDto activityResponseDto = first.get();
        promotionMessageDto.setActivityId(activityResponseDto.getActivityCode());
        promotionMessageDto.setActivityName(activityResponseDto.getActivityName());
        promotionMessageDto.setActivityType(activityResponseDto.getActivityType());
        promotionMessageDto.setPromotionAmount(0L);

        StringBuilder messageBuilder = new StringBuilder();
        ArrayList<ActivityList> activityList = new ArrayList<>();
        /**
         * 因为没有促销活动的计算信息，所以没有加入购物车内
         */
        if (null==discountResult) {
            List<BenefitBeanDto> benefitBeanDtos = activityResponseDto.getBenefits();
            BenefitBeanDto benefitBeanDto = benefitBeanDtos.get(0);
            //调用没有加入购物车的提示语的方法
            setMessageNotInShoppingCart(messageBuilder, activityResponseDto, benefitBeanDtos, benefitBeanDto, activityList);
        }
        //促销返回满减提示语
        else {
            //促销返回满减提示语
            List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.ActivityPrompt> activityPrompts = discountResult.getActivityPrompts();
            //List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> discounts = discountResult.getDiscounts();
            /**
             * 构建提示语
             */
            if (CollectionUtils.isNotEmpty(activityPrompts)) {
                setMessageSatisfyCart(messageBuilder, activityPrompts, activityResponseDto, activityList);
            }
            else {
                setMessageNoSatisfyCart(messageBuilder, discounts, activityList);
            }
        }

        promotionMessageDto.setPromotionMessage(messageBuilder.toString());
        ActivityTip activityTip = new ActivityTip();
        activityTip.setActivityCode(promotionMessageDto.getActivityId());
        activityTip.setActivityType(promotionMessageDto.getActivityType());
        activityTip.setActivityName(promotionMessageDto.getPromotionMessage());
        activityTip.setActivityList(activityList);
        shoppingCartGoodsResponseVo.setActivityTip(activityTip);
        if (discountResult == null){
            return;
        }
    }

    /**
     * 设置没有加入购物车的提示语
     * @param messageBuilder
     * @param activityResponseDto
     * @param benefitBeanDtos
     * @param benefitBeanDto
     * @param activityList
     */
    private void setMessageNotInShoppingCart(StringBuilder messageBuilder, ActivityResponseDto activityResponseDto, List<BenefitBeanDto> benefitBeanDtos, BenefitBeanDto benefitBeanDto,
                                             ArrayList<ActivityList> activityList) {

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

            //满足  x 元 减 Y 元 ，最高 减 Z元
            ActivityList notInShopping = new ActivityList();
            notInShopping.setTipType(1);
            notInShopping.setSatisfy(WebUtil.formatAmount(benefitBeanDto.getThresholdAmount() * 1.00 / 100).toString());
            notInShopping.setDeduct(WebUtil.formatAmount(benefitBeanDto.getDiscountAmount() * 1.00 / 100).toString());
            notInShopping.setMaxDeduct(WebUtil.formatAmount(activityResponseDto.getMaxMoney() * 1.00 / 100).toString());
            activityList.add(notInShopping);
        }
        else if (Objects.equals(ActivityTypeEnum.TYPE_12.getCode(), activityResponseDto.getActivityType())) {
            int len = benefitBeanDtos.size();
            // // 购物车中无商品或者存在与满减互斥的活动
            for (int i = len - 1; i >= 0; i--) {
                benefitBeanDto = benefitBeanDtos.get(i);
                messageBuilder.append("满 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(benefitBeanDto.getThresholdAmount() * 1.00 / 100))
                        .append("</span> 减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(benefitBeanDto.getDiscountAmount() * 1.00 / 100))
                        .append("</span> 元");
                if (i > 0) messageBuilder.append("，");
            }
            //  阶梯满减：满足 X 元 减 Y 元,
            for (int j = len - 1; j >= 0; j--) {
                benefitBeanDto = benefitBeanDtos.get(j);
                ActivityList notInShopping = new ActivityList();
                notInShopping.setTipType(2);
                notInShopping.setSatisfy(WebUtil.formatAmount(benefitBeanDto.getThresholdAmount() * 1.00 / 100).toString());
                notInShopping.setDeduct(WebUtil.formatAmount(benefitBeanDto.getDiscountAmount() * 1.00 / 100).toString());
                activityList.add(notInShopping);
            }
        }
        if (Objects.equals(ActivityTypeEnum.TYPE_230.getCode(), activityResponseDto.getActivityType())) {
            ActivityList notInShopping = new ActivityList();
            // 规则:满5赠奶茶2件，炸鸡1件，满10赠布丁3件，牛奶1份，鸡翅2份，
            // 提示语：满5元可获赠奶茶*2，炸鸡*1
            //阶梯满赠
            if (GiftTypeEnum.TYPE_1.getType().equals(activityResponseDto.getActivitySubType())) {
                notInShopping.setTipType(6);
            }
            //每满赠
            else if (GiftTypeEnum.TYPE_2.getType().equals(activityResponseDto.getActivitySubType())) {
                notInShopping.setTipType(7);
            }
            Collections.sort(benefitBeanDtos);
            BenefitBeanDto dto = benefitBeanDtos.get(0);
            int len = dto.getSendGoodsList().size();
            notInShopping.setSatisfy(WebUtil.formatAmount(dto.getThresholdAmount() * 1.00 / 100).toString());
            List<ActivityList.SendGoods> sends = new ArrayList();
            for (int i = 0; i < len; i++) {
                ActivityList.SendGoods goods = new ActivityList.SendGoods();
                goods.setQty(dto.getSendGoodsList().get(i).getSendNumber());
                goods.setGoodsName(dto.getSendGoodsList().get(i).getGoodsName());
                sends.add(goods);
            }
            notInShopping.setSends(sends);
            activityList.add(notInShopping);
        }
    }

    /**
     * 设置加入商品满足购物车时的提示语
     *
     * @param messageBuilder
     * @param activityPrompts
     * @param activityResponseDto
     */
    private void setMessageSatisfyCart(StringBuilder messageBuilder, List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.ActivityPrompt> activityPrompts
            , ActivityResponseDto activityResponseDto, ArrayList<ActivityList> activityList) {

        ActivityList satisfyList = new ActivityList();
        CalculationSharingDiscountResponseDto.CalculationDiscountResult.ActivityPrompt activityPrompt = activityPrompts.get(0);
        if (Objects.equals(ActivityTypeEnum.TYPE_11.getCode(), activityResponseDto.getActivityType()) || Objects.equals(ActivityTypeEnum.TYPE_12.getCode(), activityResponseDto.getActivityType())) {
            if (activityPrompt.getAlreadyDiscountAmount() == null || activityPrompt.getAlreadyDiscountAmount() == 0) {
                messageBuilder.append("满 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(activityPrompt.getThresholdAmount() * 1.00 / 100))
                        .append("</span> 减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100))
                        .append("</span> ")
                        .append("还差 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100))
                        .append("</span> 元");
                // 满足 X 元 减 Y 元 还差 Z元
                satisfyList.setTipType(3);
                satisfyList.setSatisfy(WebUtil.formatAmount(activityPrompt.getThresholdAmount() * 1.00 / 100).toString());
                satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getDiscountAmout() * 1.00 / 100).toString());
                satisfyList.setMissing(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100).toString());
            } else {
                Long toDiscountAmout;
                if (Objects.equals(ActivityTypeEnum.TYPE_11.getCode(), activityResponseDto.getActivityType())) {
                    toDiscountAmout = activityPrompt.getDiscountAmout() + activityPrompt.getAlreadyDiscountAmount();
                } else {
                    toDiscountAmout = activityPrompt.getDiscountAmout();
                }
                //已减 X 元 再买 Y 元 减 Z 元
                messageBuilder.append("已减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100))
                        .append("</span> 元 再买 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100))
                        .append("</span> 元减 <span style=\"color:#fa5555\">")
                        .append(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100))
                        .append("</span> 元");
                satisfyList.setTipType(4);
                satisfyList.setDeduct(WebUtil.formatAmount(activityPrompt.getAlreadyDiscountAmount() * 1.00 / 100).toString());
                satisfyList.setAgainBuy(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100).toString());
                satisfyList.setAgianDeduct(WebUtil.formatAmount(toDiscountAmout * 1.00 / 100).toString());
            }
        }
        if (Objects.equals(ActivityTypeEnum.TYPE_230.getCode(), activityResponseDto.getActivityType()) && CollectionUtils.isNotEmpty(activityPrompt.getSendGoods())) {

            satisfyList.setTipType(10);
            List<ActivityList.SendGoods> sends = new ArrayList();
            for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.SendGoods sendGood : activityPrompt.getSendGoods()) {
                ActivityList.SendGoods send = new ActivityList.SendGoods();
                send.setGoodsName(sendGood.getGoodsName());
                send.setQty(sendGood.getSendNumber());
                sends.add(send);
            }
            satisfyList.setSends(sends);
            satisfyList.setSatisfy(WebUtil.formatAmount(activityPrompt.getThresholdAmount() * 1.00 / 100).toString());
            satisfyList.setMissing(WebUtil.formatAmount((activityPrompt.getThresholdAmount() - activityPrompt.getTotalAmount()) * 1.00 / 100).toString());
            if (GiftTypeEnum.TYPE_1.getType().equals(activityResponseDto.getActivitySubType())) {
                satisfyList.setTipType(8);
            }
            else {
                satisfyList.setTipType(7);
            }
            if (activityPrompt.getTotalAmount()>=activityPrompt.getThresholdAmount()) {
                if (GiftTypeEnum.TYPE_1.getType().equals(activityResponseDto.getActivitySubType())) {
                    satisfyList.setTipType(10);
                }
                else {
                    satisfyList.setTipType(7);
                }
            }
        }
        activityList.add(satisfyList);
    }


    /**
     * 设置加入商品不满足购物车时的提示语
     *
     * @param messageBuilder
     * @param discountList
     */
    private void setMessageNoSatisfyCart(StringBuilder messageBuilder, List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> discountList, ArrayList<ActivityList> activityList) {
        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;
        }
        //已减 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);
    }

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