package cn.freemud.service.impl;

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.CalculationDiscountResult;
import cn.freemud.entities.dto.calculate.SendActivity;
import cn.freemud.entities.dto.calculate.SendGoods;
import cn.freemud.entities.dto.product.info.AttributeValueBean;
import cn.freemud.entities.dto.product.info.ProductAttributeGroupListBean;
import cn.freemud.entities.dto.product.info.ProductBean;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.ActivityTypeEnum;
import cn.freemud.enums.ResponseResult;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.IPromotionService;
import cn.freemud.service.cache.GiftCacheManager;
import cn.freemud.service.product.ProductInfoManager;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * All rights Reserved, Designed By www.freemud.cn
 * 买赠活动
 * 例如：买烧饼送手提袋
 *
 * @version V1.0
 * @Title: BuyAndGiftsPromotionService
 * @Package cn.freemud.service.impl
 * @Description:
 * @author: jiaxin.liu
 * @date: 2019/4/18 11:00
 * @Copyright: 2019 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
public class BuyAndGiftsPromotionService implements IPromotionService {

    @Autowired
    private GiftCacheManager giftCacheManager;
    @Autowired
    private ProductInfoManager productInfoManager;

    @Override
    public void updateShoppingCartGoodsDiscount(CouponPromotionVO couponPromotionVO, ActivityQueryDto activityQueryDto,
                                                CalculationDiscountResult calculationDiscountResult,
                                                List<CartGoods> cartGoodsList, ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo,
                                                UserLoginInfoDto userLoginInfoDto, ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {
        if (calculationDiscountResult == null || CollectionUtils.isEmpty(calculationDiscountResult.getSendGoods())) {
            return;
        }
        List<SendActivity> sendActivities = calculationDiscountResult.getSendGoods().stream()
                .filter(goods -> (ActivityTypeEnum.TYPE_62.getCode().equals(goods.getActivityType())) || (ActivityTypeEnum.TYPE_230.getCode().equals(goods.getActivityType())))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sendActivities)) {
            return;
        }
        List<SendGoods> sendGoodsList = new ArrayList<>();
        sendActivities.forEach(sendActivity -> sendGoodsList.addAll(sendActivity.getSendGoods()));
        List<ProductBean> productBeanDTOS = buildActivityProduct(activityQueryDto, sendGoodsList,shoppingCartInfoRequestVo==null?null:shoppingCartInfoRequestVo.getMenuType());
        if (CollectionUtils.isEmpty(productBeanDTOS)) {
            return;
        }

        Long totalGiftAmount = 0L;
        for (SendActivity sendActivity : sendActivities) {
            List<CartGoods> list = new ArrayList<>();
            for (SendGoods sendGoods : sendActivity.getSendGoods()) {
                Optional<ProductBean> firstProduct = productBeanDTOS.stream().filter(productBean -> ObjectUtils.equals(productBean.getPid(), sendGoods.getGoodsId())).findFirst();
                if (!firstProduct.isPresent()) {
                    continue;
                }
                ProductBean product = firstProduct.get();
                CartGoods cartGoods = new CartGoods();
                cartGoods.setGoodsId(sendGoods.getGoodsId());
                cartGoods.setGoodsType(1);
                cartGoods.setSpuId(Objects.equals(product.getIsSkuProduct(), 1) ? product.getSpecProductId() : sendGoods.getGoodsId());
                cartGoods.setSkuId(sendGoods.getGoodsId());
                cartGoods.setOriginalPrice(product.getFinalPrice());
                cartGoods.setPackPrice(product.getPackPrice());
                cartGoods.setOriginalAmount(product.getFinalPrice() * sendGoods.getSendNumber());
                cartGoods.setAmount(0L);
                cartGoods.setName(product.getName());
                cartGoods.setSpuName(product.getName());
                cartGoods.setCategoryName(product.getName());
                cartGoods.setPic(product.getPicture());
                cartGoods.setSkuName(product.getName());
                cartGoods.setActivityType(sendActivity.getActivityType());
                cartGoods.setActivityCode(sendActivity.getActivityCode());
                cartGoods.setStockLimit(ObjectUtils.equals(1, product.getStockLimit()));
                cartGoods.setCustomerCode(product.getCustomerCode());
                cartGoods.setUnit(product.getUnit());
                cartGoods.setWeight(product.getWeight());
                cartGoods.setQty(sendGoods.getSendNumber());
                cartGoods.setClassificationId(product.getCategory());
                cartGoods.setClassificationName(product.getCategoryName());
                // nodeId标识activeCode,用于计算均摊时每个商品在每个活动上均摊金额
                cartGoods.setNodeId(sendActivity.getActivityCode());
                cartGoods.setOriginalGoodsUid(sendGoods.getOriginalGoodsUid());
                cartGoods.setIsSendGoods(true);
                list.addAll(this.setGiftExtra(cartGoods,product,cartGoodsList));
                totalGiftAmount += product.getFinalPrice() * sendGoods.getSendNumber();
            }
            cartGoodsList.addAll(giftCacheManager.resetGiftCache(list, sendActivity.getActivityCode(), activityQueryDto.getPartnerId(), activityQueryDto.getStoreId(), userLoginInfoDto.getMemberId()));
        }


        shoppingCartGoodsResponseVo.setOriginalTotalAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount() + totalGiftAmount);
        Long totalDiscountAmount = Objects.isNull(shoppingCartGoodsResponseVo.getTotalDiscountAmount()) ? 0L : shoppingCartGoodsResponseVo.getTotalDiscountAmount();
        shoppingCartGoodsResponseVo.setTotalDiscountAmount(totalDiscountAmount + totalGiftAmount);

    }

    @Override
    public void updateShoppingCartGoodsApportion(ShoppingCartGoodsResponseVo shoppingCartGoodsResponseVo, CalculationDiscountResult calculationDiscountResult, ShoppingCartGoodsDto shoppingCartGoodsDto, CreateOrderVo.PremiumExchangeActivity premiumExchangeActivity, ShoppingCartInfoRequestVo shoppingCartInfoRequestVo) {
        if (calculationDiscountResult == null || CollectionUtils.isEmpty(calculationDiscountResult.getSendGoods())) {
            return;
        }
        List<SendActivity> sendActivities = calculationDiscountResult
                .getSendGoods()
                .stream()
                .filter(goods -> (ActivityTypeEnum.TYPE_62.getCode().equals(goods.getActivityType()) || ActivityTypeEnum.TYPE_230.getCode().equals(goods.getActivityType())))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sendActivities)) {
            return;
        }

        List<ShoppingCartGoodsDto.CartGoodsDetailDto> sendGoodsList = shoppingCartGoodsDto
                .getProducts()
                .stream()
                .filter(product -> (ActivityTypeEnum.TYPE_62.getCode().equals(product.getActivityType()) || ActivityTypeEnum.TYPE_230.getCode().equals(product.getActivityType())))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sendGoodsList)) {
            return;
        }
        List<ActivityDiscountsDto> activityDiscountsDtos = shoppingCartGoodsDto.getActivityDiscountsDtos() == null ? new ArrayList<>() : shoppingCartGoodsDto.getActivityDiscountsDtos();
        //设置商品行活动均摊
        for (ShoppingCartGoodsDto.CartGoodsDetailDto cartGoodsDetailDto : sendGoodsList) {
            Optional<SendActivity> first =
                    sendActivities.stream()
                    .filter(sendActivity -> ObjectUtils.equals(sendActivity.getActivityCode(), cartGoodsDetailDto.getNodeId()))
                    .findFirst();
            if (!first.isPresent()) {
                continue;
            }
            SendActivity sendActivity = first.get();
            ActivityDiscountsDto ProductActivityDiscountsDto = new ActivityDiscountsDto();
            ProductActivityDiscountsDto.setActivityCode(sendActivity.getActivityCode());
            ProductActivityDiscountsDto.setActivityName(sendActivity.getActivityName());
            ProductActivityDiscountsDto.setActivityType(sendActivity.getActivityType());
            if (cartGoodsDetailDto.getActivityType().equals(ActivityTypeEnum.TYPE_230.getCode())) {
                cartGoodsDetailDto.setTotalDiscountAmount(cartGoodsDetailDto.getOriginalPrice().intValue()*cartGoodsDetailDto.getQty());
                ProductActivityDiscountsDto.setDiscountAmount(cartGoodsDetailDto.getOriginalPrice().intValue()*cartGoodsDetailDto.getQty());
            }
            else {
                ProductActivityDiscountsDto.setDiscountAmount(cartGoodsDetailDto.getTotalDiscountAmount());
            }
            cartGoodsDetailDto.setActivityDiscountsDtos(Arrays.asList(ProductActivityDiscountsDto));
        }
        //设置活动级别的均摊
        boolean type230 = false;
        for (SendActivity sendActivity : sendActivities) {
            if (ActivityTypeEnum.TYPE_230.getCode().toString().equals(sendActivity.getActivityCode())) {
                type230 = true;
            }
            //设置优惠活动
            Integer totalDiscountAmount = sendGoodsList
                    .stream()
                    .filter(sendGoods -> ObjectUtils.equals(sendActivity.getActivityCode(), sendGoods.getNodeId()))
                    .mapToInt(sendGoods -> sendGoods.getTotalDiscountAmount())
                    .sum();
            Long totalDiscountOriginalAmount = sendGoodsList
                    .stream()
                    .filter(sendGoods -> ObjectUtils.equals(sendActivity.getActivityCode(), sendGoods.getNodeId()))
                    .mapToLong(sendGoods -> sendGoods.getOriginalPrice()*sendGoods.getQty())
                    .sum();
            ActivityDiscountsDto activityDiscountsDto = new ActivityDiscountsDto();
            activityDiscountsDto.setActivityCode(sendActivity.getActivityCode());
            activityDiscountsDto.setActivityName(sendActivity.getActivityName());
            activityDiscountsDto.setActivityType(sendActivity.getActivityType());
            activityDiscountsDto.setDiscountAmount(type230 ? 0 - totalDiscountOriginalAmount.intValue() :   0 - totalDiscountAmount);
            activityDiscountsDtos.add(activityDiscountsDto);
        }
    }

    /**
     * @param activityQueryDto
     * @param sendGoodsList
     * @return
     */
    private List<ProductBean> buildActivityProduct(ActivityQueryDto activityQueryDto, List<SendGoods> sendGoodsList,String menuType) {
        //获取
        List<String> goodsIds = sendGoodsList.stream().map(SendGoods::getGoodsId).collect(Collectors.toList());
        List<ProductBean> list = productInfoManager.getProductsInfo(activityQueryDto.getPartnerId(), activityQueryDto.getStoreId(), menuType, true, goodsIds);
        if (CollectionUtils.isEmpty(list)) {
            throw new ServiceException(ResponseResult.SHOPPING_CART_GIFTS_PRODUCT_NOT_EXIST);
        }
        return list;
    }


    /**
     * 设置赠品的属性， 默认选择第一个属性， 如果购物车有同样商品，则和购物车商品属性一致
     * @param cartGoods 赠品的购物车行
     * @param product 商品信息
     * @param cartGoodsList 现购物车行信息
     * @return 如果赠品有多个，则会分裂为多行返回
     */
    public List<CartGoods> setGiftExtra(CartGoods cartGoods, ProductBean product, List<CartGoods> cartGoodsList) {
        List<CartGoods> result = new ArrayList<>();
        result.add(cartGoods);

        long count = cartGoodsList.stream().filter(c -> c.getSpuId().equals(cartGoods.getSpuId())).count();
        //购物车内存在同类
        if (count>0) {
            CartGoods find = cartGoodsList.stream().filter(c -> c.getCartGoodsUid().equals(cartGoods.getOriginalGoodsUid())).findFirst().orElse(null);
            if (null == find) {
                find = cartGoodsList.stream().filter(c -> c.getSpuId().equals(cartGoods.getSpuId())).findFirst().get();
            }
            cartGoods.setExtra(find.getExtra());
            cartGoods.setSpuName(find.getSpuName());
            cartGoods.setSkuName(find.getSkuName());
            cartGoods.setSubName(find.getSubName());
        }
        //不存在
        else {
            if (product.getProductAttributeGroupList().size() > 0) {
                List<CartGoods.CartGoodsExtra> extra = new ArrayList<>();
                ArrayList<String> name = new ArrayList<>();
                List<ProductAttributeGroupListBean> productAttributeGroupList = product.getProductAttributeGroupList();
                for (ProductAttributeGroupListBean productAttributeGroupListBean : productAttributeGroupList) {
                    AttributeValueBean bean = productAttributeGroupListBean.getAttributeValues().stream().findFirst().get();

                    CartGoods.CartGoodsExtra goodsExtra = new CartGoods.CartGoodsExtra();
                    goodsExtra.setAttributeId(bean.getAttributeId());
                    goodsExtra.setAttributeName(bean.getAttributeValue());
                    name.add(bean.getAttributeValue());
                    extra.add(goodsExtra);
                }
                cartGoods.setExtra(extra);
                cartGoods.setSubName(StringUtils.join(name, "/"));
            }
        }

        //如果赠品有属性，并且赠送的数量大于1，则分裂为多行，每行数量为1，这样前端可以为每一个赠品选择不同属性
        if (CollectionUtils.isNotEmpty(cartGoods.getExtra()) && cartGoods.getQty() > 1) {
            int qty = cartGoods.getQty();
            cartGoods.setQty(1); //设置数量为1
            for (int i=1; i<qty; i++) {
                CartGoods newRow = new CartGoods();
                BeanUtils.copyProperties(cartGoods, newRow);
                newRow.setCartGoodsUid(UUID.randomUUID().toString());
                newRow.setQty(1);
                result.add(newRow);
            }
        }
        return result;
    }
}
