package cn.freemud.service.impl.calculate;

import cn.freemud.constant.ShoppingCartConstant;
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.calculate.CalculationSharingDiscountResponseDto;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.ActivityTypeEnum;
import cn.freemud.service.impl.calculate.promotion.*;
import com.freemud.sdk.api.assortment.shoppingcart.enums.BusinessTypeEnum;
import lombok.extern.slf4j.Slf4j;
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 CalculationSharingEquallyService
 * @Description: TDO 描述....
 * @author: family
 * @date: 2020/9/14
 * @Copyright: www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
@Slf4j
public class CalculationSharingEquallyService {

    @Autowired
    private CalculationCommonService calculationCommonService;
    @Autowired
    private GiftSharingService giftSharingService;
    @Autowired
    private ScoreSharingService scoreSharingService;

    @Autowired
    private DeliverySharingService deliverySharingService;

    @Autowired
    private AdditionSharingService additionSharingService;

    @Autowired
    private CouponSharingService promotionSharingService;

    /**
     * 均摊服务
     * @param discountResult
     * @param cartGoodsList
     * @param shoppingCartGoodsResponseVo
     * @param shoppingCartInfoRequestVo
     * @param userLoginInfoDto
     * @param couponPromotionVO
     * @param activityQueryDto
     * @param menuType
     * @param deliveryAmount
     * @param shoppingCartGoodsDto
     * @param premiumExchangeActivity
     */
    public void equally(CalculationSharingDiscountResponseDto.CalculationDiscountResult discountResult
            , List<CartGoods> cartGoodsList
            , ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo
            , ShoppingCartInfoRequestVo shoppingCartInfoRequestVo
            , UserLoginInfoDto userLoginInfoDto
            , CouponPromotionVO couponPromotionVO
            , ActivityQueryDto activityQueryDto
            , String menuType
            , Long deliveryAmount
            , ShoppingCartGoodsDto shoppingCartGoodsDto
            , CreateOrderVo.PremiumExchangeActivity premiumExchangeActivity) {


        calculationCommonService.initShoppingCart(discountResult, cartGoodsList, shoppingCartGoodsResponseVo);
        /**
         * 商品券\换购券
         */
        promotionSharingService.equally(discountResult, cartGoodsList);
        List<ShoppingCartGoodsDto.CartGoodsDetailDto> cartGoodsDetailDtoList = CollectionUtils.isEmpty(shoppingCartGoodsDto.getProducts()) ? new ArrayList<>() : shoppingCartGoodsDto.getProducts();
        shoppingCartGoodsDto.setProducts(cartGoodsDetailDtoList);

        /**
         * 组建大的优惠信息
         */
        this.setShoppingCartGoodsDtoActivityDiscounts(discountResult, shoppingCartGoodsDto);
        /**
         * 活动库存
         * 过滤出加价购
         */
        List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> addMoneyDiscounts = discountResult.getDiscounts()
                .stream()
                .filter(discount -> ActivityTypeEnum.TYPE_81.getCode().equals(discount.getType()))
                .collect(Collectors.toList());
        if (null != discountResult) {
            List<SubtractStockVO> stocks = filterSendGoodsStocks(discountResult.getStocks(), shoppingCartInfoRequestVo, addMoneyDiscounts);
            if (CollectionUtils.isNotEmpty(stocks)) shoppingCartGoodsDto.setStocks(stocks);
        }

        List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods> goods = discountResult.getGoods();

        /**
         * 利用促销赋值totalDiscountAmount
         */
        shoppingCartGoodsResponseVo.setProducts(cartGoodsList);
        for (CartGoods product : shoppingCartGoodsResponseVo.getProducts()) {
            CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods find = goods.stream().filter((k) -> k.getCartGoodsUid().equals(product.getCartGoodsUid())).findFirst().get();
            ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto = calculationCommonService.convertCartGoods2DetailGoodsList(find, product);
            cartGoodsDetailDtoList.add(cartGoodsDetailDto);
        }

        /**
         * 赠品
         */
        giftSharingService.equally(discountResult, cartGoodsDetailDtoList, activityQueryDto, menuType);

        /**
         * 加价购商品
         */
        additionSharingService.equally(shoppingCartInfoRequestVo, shoppingCartGoodsDto, discountResult, premiumExchangeActivity);
        /**
         * 积分抵扣
         */
        scoreSharingService.scoreResponse(discountResult, shoppingCartGoodsResponseVo, userLoginInfoDto, shoppingCartInfoRequestVo);
        scoreSharingService.equally(shoppingCartGoodsResponseVo, shoppingCartGoodsDto);
        calculationCommonService.getNeedCardAmount(shoppingCartInfoRequestVo, shoppingCartGoodsDto);

        if (BusinessTypeEnum.SAAS_DELIVERY.getCode().equals(menuType)) {
            deliverySharingService.deliveryResponse(discountResult, activityQueryDto, shoppingCartGoodsResponseVo, deliveryAmount);
        }

        calculationCommonService.setAddAndUpdateResponse(cartGoodsList, shoppingCartGoodsResponseVo, shoppingCartInfoRequestVo, ShoppingCartConstant.QUERY_INFO);
        calculationCommonService.addNeedCardAmount(shoppingCartInfoRequestVo, shoppingCartGoodsResponseVo);

        shoppingCartGoodsDto.setDeliveryAmount(shoppingCartGoodsResponseVo.getDeliveryAmount());
        shoppingCartGoodsDto.setDiscountDeliveryAmount(shoppingCartGoodsResponseVo.getDiscountDeliveryAmount());
        shoppingCartGoodsDto.setThresholdAmount(shoppingCartGoodsResponseVo.getThresholdAmount());
        shoppingCartGoodsDto.setIsDiscountDelivery(shoppingCartGoodsResponseVo.getIsDiscountDelivery());
        shoppingCartGoodsDto.setDiscountDeliveryActivityCode(shoppingCartGoodsResponseVo.getDiscountDeliveryActivityCode());
        //总计价
        shoppingCartGoodsDto.setPackageAmount(shoppingCartGoodsResponseVo.getNewPackAmount());
        shoppingCartGoodsDto.setOriginalTotalAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount());
        shoppingCartGoodsDto.setTotalAmount(shoppingCartGoodsResponseVo.getTotalAmount());
        shoppingCartGoodsDto.setTotalDiscountAmount(shoppingCartGoodsResponseVo.getTotalDiscountAmount());
    }

    /**
     * 设置购物车整体享受的活动集合
     *
     * @param discountResult
     * @param shoppingCartGoodsDto
     */
    public void setShoppingCartGoodsDtoActivityDiscounts(CalculationSharingDiscountResponseDto.CalculationDiscountResult discountResult
            , ShoppingCartGoodsDto shoppingCartGoodsDto) {


        List<ActivityDiscountsDto> activityDiscountsDtos = new ArrayList<>();
        shoppingCartGoodsDto.setActivityDiscountsDtos(activityDiscountsDtos);
        if (discountResult == null) return;
        Integer type = 2;
        List<ActivityTypeEnum> activityTypeEnums = new LinkedList<>();
        activityTypeEnums.add(ActivityTypeEnum.TYPE_11);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_12);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_3);
        activityTypeEnums.add(ActivityTypeEnum.TYPE_31);
        List<Integer> typeEnums = activityTypeEnums.stream().map(ActivityTypeEnum::getCode).collect(Collectors.toList());
        for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods good : discountResult.getGoods()) {
            if (CollectionUtils.isNotEmpty(good.getSmallMaterial())) {
                List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods.SmallMaterial> sm = good.getSmallMaterial()
                        .stream()
                        .filter(d -> type.equals(d.getType())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(sm)) continue;
                for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods.SmallMaterial s : sm) {
                    if (CollectionUtils.isEmpty(s.getDiscounts())) continue;
                    HashMap<Integer, Long> discountMap = new HashMap<>();
                    for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods.GoodsDiscount d : s.getDiscounts()) {
                        if (!typeEnums.contains(d.getType())) continue;
                        Integer sType = d.getType();
                        discountMap.put(sType, d.getDiscount());
                    }

                    if (discountMap.isEmpty()) continue;
                    if (CollectionUtils.isEmpty(good.getDiscounts())) continue;
                    for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.Goods.GoodsDiscount discount : good.getDiscounts()) {
                        Integer mType = discount.getType();
                        if (discountMap.get(mType) != null) {
                            discount.setDiscount(discount.getDiscount() + discountMap.get(mType).longValue());
                        }
                    }
                }
            }
        }
        List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> discounts = discountResult.getDiscounts();
        for (CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount discount : discounts) {
            int discountAmount = (discount.getDiscount() == null) ? 0 : discount.getDiscount();
            Integer discountType = discount.getType();
            if (discountType != null && discountAmount > 0) {
                ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
                activityDiscountsDto.setActivityCode(discount.getActivityCode());
                activityDiscountsDto.setActivityName(discount.getActivityName());
                activityDiscountsDto.setActivityType(calculationCommonService.convertType(discountType));
                activityDiscountsDto.setDiscountAmount(0 - discountAmount);
                activityDiscountsDtos.add(activityDiscountsDto);
            }
        }
        shoppingCartGoodsDto.setActivityDiscountsDtos(activityDiscountsDtos);
    }


    /**
     * 库存扣减加价购商品 要过滤掉没有换购的商品
     *
     * @param stocks                    扣减库存
     * @param shoppingCartInfoRequestVo 购物车请求信息
     * @param addMoneyDiscounts         加价购活动
     * @return 返回应该扣减的加价购商品库存
     */
    private List<SubtractStockVO> filterSendGoodsStocks(List<SubtractStockVO> stocks
            , ShoppingCartInfoRequestVo shoppingCartInfoRequestVo
            , List<CalculationSharingDiscountResponseDto.CalculationDiscountResult.Discount> addMoneyDiscounts) {
        if (CollectionUtils.isEmpty(stocks) || CollectionUtils.isEmpty(addMoneyDiscounts)) {
            return stocks;
        }
        List<SubtractStockVO> subtractStockVOs = stocks.stream().filter(subtractStockVO -> ActivityTypeEnum.TYPE_81.getCode().equals(subtractStockVO.getActivityType())).collect(Collectors.toList());
        List<SubtractStockVO.SubtractStockGoodsVO> goodsStock = null;
        if (CollectionUtils.isNotEmpty(subtractStockVOs)) {
            SubtractStockVO subtractStockVO = subtractStockVOs.get(0);
            goodsStock = subtractStockVO.getGoodsStock();
        }
        if (null == goodsStock) {
            return stocks;
        }
        Map<String, SubtractStockVO.SubtractStockGoodsVO> mapSubstractStocks = new HashMap<>();
        if (CollectionUtils.isNotEmpty(goodsStock)) {
            mapSubstractStocks = goodsStock.stream().collect(Collectors.toMap(SubtractStockVO.SubtractStockGoodsVO::getGoodsId, Function.identity(), (k1, k2) -> k1));
        }
        //获取加价购商品
        List<ShoppingCartInfoRequestVo.SendGoods> sendGoods = shoppingCartInfoRequestVo.getSendGoods();
        if (CollectionUtils.isNotEmpty(sendGoods)) {
            List<String> needSendGoodsId = sendGoods.stream().map(ShoppingCartInfoRequestVo.SendGoods::getGoodsId).collect(Collectors.toList());
            goodsStock.clear();
            for (String goodId : needSendGoodsId) {
                SubtractStockVO.SubtractStockGoodsVO subtractStockGoodsVO = mapSubstractStocks.get(goodId);
                if (null != mapSubstractStocks.get(goodId)) {
                    goodsStock.add(subtractStockGoodsVO);
                }
            }
        } else {
            return stocks.stream().filter(subtractStockVO -> !ActivityTypeEnum.TYPE_81.getCode().equals(subtractStockVO.getActivityType())).collect(Collectors.toList());
        }
        return stocks;
    }

}
