package cn.lili.modules.order.cart.render.impl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
import cn.lili.modules.order.cart.render.CartRenderStep;
import cn.lili.modules.order.cart.render.util.PromotionPriceUtil;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dto.search.MemberCouponSearchParams;
import cn.lili.modules.promotion.entity.enums.CouponTypeEnum;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum;
import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum;
import cn.lili.modules.promotion.entity.vos.MemberCouponVO;
import cn.lili.modules.promotion.service.MemberCouponService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 购物促销信息渲染实现
 *
 * @author Chopper
 * @since 2020-07-02 14:47
 */
@Service
public class CouponRender implements CartRenderStep {

    @Autowired
    private PromotionPriceUtil promotionPriceUtil;
    @Autowired
    private MemberCouponService memberCouponService;

    @Override
    public RenderStepEnums step() {
        return RenderStepEnums.COUPON;
    }

    @Override
    public void render(TradeDTO tradeDTO) {

        //优惠券列表
        this.renderCouponRule(tradeDTO);
        //主要渲染各个优惠的价格
        this.renderCoupon(tradeDTO);
    }


    /**
     * 渲染优惠券规则
     *
     * @param tradeDTO 交易dto
     */
    private void renderCouponRule(TradeDTO tradeDTO) {
        MemberCouponSearchParams searchParams = new MemberCouponSearchParams();
        searchParams.setMemberId(UserContext.getCurrentUser().getId());
        searchParams.setMemberCouponStatus(MemberCouponStatusEnum.NEW.name());
        searchParams.setPromotionStatus(PromotionsStatusEnum.START.name());
        List<MemberCoupon> memberCouponList = memberCouponService.getMemberCoupons(searchParams);

        if (!memberCouponList.isEmpty()) {
            this.checkMemberExistCoupon(tradeDTO, memberCouponList);
        } else {
            tradeDTO.setPlatformCoupon(null);
            tradeDTO.setStoreCoupons(new HashMap<>());
        }
        memberCouponList.forEach(memberCoupon -> available(tradeDTO, memberCoupon));
    }

    /**
     * 检查使用中的优惠券是否存在与用户的优惠券中
     *
     * @param tradeDTO         交易dto
     * @param memberCouponList 会员优惠券列表
     */
    private void checkMemberExistCoupon(TradeDTO tradeDTO, List<MemberCoupon> memberCouponList) {
        if (tradeDTO.getPlatformCoupon() != null && tradeDTO.getPlatformCoupon().getMemberCoupon() != null) {
            boolean b = memberCouponList.stream().anyMatch(i -> i.getId().equals(tradeDTO.getPlatformCoupon().getMemberCoupon().getId()));
            if (!b) {
                tradeDTO.setPlatformCoupon(null);
            }
        }
        if (!tradeDTO.getStoreCoupons().isEmpty()) {
            for (Map.Entry<String, MemberCouponDTO> entry : tradeDTO.getStoreCoupons().entrySet()) {
                if (entry.getValue().getMemberCoupon() != null && memberCouponList.stream().noneMatch(i -> i.getId().equals(entry.getValue().getMemberCoupon().getId()))) {
                    tradeDTO.getStoreCoupons().remove(entry.getKey());
                }
            }
        }
    }

    /**
     * 判定优惠券是否可用
     *
     * @param tradeDTO     交易dto
     * @param memberCoupon 会员优惠券
     */
    private void available(TradeDTO tradeDTO, MemberCoupon memberCoupon) {
        if (memberCoupon == null) {
            return;
        }
        List<CartSkuVO> filterSku = filterSkuVo(tradeDTO.getCheckedSkuList(), memberCoupon);
        if (filterSku == null || filterSku.isEmpty()) {
            tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon,
                    "购物车中没有满足优惠券使用范围的优惠券"));
            return;
        }
        List<PriceDetailDTO> priceDetailDTOS =
                filterSku.stream().map(CartSkuVO::getPriceDetailDTO).collect(Collectors.toList());

        PriceDetailDTO totalPrice = new PriceDetailDTO();
        totalPrice.accumulationPriceDTO(priceDetailDTOS);

        //满足条件判定
        if (totalPrice.getGoodsPrice() >= memberCoupon.getConsumeThreshold()) {
            tradeDTO.getCanUseCoupons().add(memberCoupon);
        } else {
            tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon,
                    "优惠券使用门槛不足，还差" +
                            StringUtils.toFen(CurrencyUtil.sub(memberCoupon.getConsumeThreshold(), totalPrice.getGoodsPrice())) +
                            "元"));
        }

    }

    /**
     * 过滤购物车商品信息，按照优惠券的适用范围过滤
     *
     * @param cartSkuVOS   购物车中的产品列表
     * @param memberCoupon 会员优惠券
     * @return 按照优惠券的适用范围过滤的购物车商品信息
     */
    private List<CartSkuVO> filterSkuVo(List<CartSkuVO> cartSkuVOS, MemberCoupon memberCoupon) {

        List<CartSkuVO> filterSku;
        //平台店铺过滤
        if (Boolean.TRUE.equals(memberCoupon.getPlatformFlag())) {
            filterSku = cartSkuVOS;
        } else {
            filterSku = cartSkuVOS.stream().filter(cartSkuVO -> cartSkuVO.getStoreId().equals(memberCoupon.getStoreId())).collect(Collectors.toList());
        }
        if (filterSku == null || filterSku.isEmpty()) {
            return Collections.emptyList();
        }
        //优惠券类型判定
        switch (PromotionsScopeTypeEnum.valueOf(memberCoupon.getScopeType())) {
            case ALL:
                return filterSku;
            case PORTION_GOODS:
                //按照商品过滤
                filterSku = filterSku.stream().filter(cartSkuVO -> memberCoupon.getScopeId().contains(cartSkuVO.getGoodsSku().getId())).collect(Collectors.toList());
                break;

            case PORTION_SHOP_CATEGORY:
                //按照店铺分类过滤
                filterSku = this.filterPromotionShopCategory(filterSku, memberCoupon);
                break;

            case PORTION_GOODS_CATEGORY:

                //按照店铺分类过滤
                filterSku = filterSku.stream().filter(cartSkuVO -> {
                    //平台分类获取
                    String[] categoryPath = cartSkuVO.getGoodsSku().getCategoryPath().split(",");
                    //平台三级分类
                    String categoryId = categoryPath[categoryPath.length - 1];
                    return memberCoupon.getScopeId().contains(categoryId);
                }).collect(Collectors.toList());
                break;
            default:
                return Collections.emptyList();
        }
        return filterSku;
    }

    /**
     * 优惠券按照店铺分类过滤
     *
     * @param filterSku    过滤的购物车商品信息
     * @param memberCoupon 会员优惠
     * @return 优惠券按照店铺分类过滤的购物车商品信息
     */
    private List<CartSkuVO> filterPromotionShopCategory(List<CartSkuVO> filterSku, MemberCoupon memberCoupon) {
        return filterSku.stream().filter(cartSkuVO -> {
            if (CharSequenceUtil.isNotEmpty(cartSkuVO.getGoodsSku().getStoreCategoryPath())) {
                //获取店铺分类
                String[] storeCategoryPath = cartSkuVO.getGoodsSku().getStoreCategoryPath().split(",");
                for (String category : storeCategoryPath) {
                    //店铺分类只要有一项吻合，即可返回true
                    if (memberCoupon.getScopeId().contains(category)) {
                        return true;
                    }
                }
            }
            return false;
        }).collect(Collectors.toList());
    }

    /**
     * 渲染优惠券
     *
     * @param tradeDTO 购物车展示信息
     */
    private void renderCoupon(TradeDTO tradeDTO) {
        MemberCouponDTO platformCoupon = tradeDTO.getPlatformCoupon();
        //如果有勾选平台优惠券
        if (platformCoupon != null) {
            renderSku(tradeDTO, platformCoupon);
        }
        //计算商家优惠券
        Map<String, MemberCouponDTO> map = tradeDTO.getStoreCoupons();
        if (map != null && map.size() > 0) {
            for (MemberCouponDTO memberCouponDTO : map.values()) {
                renderSku(tradeDTO, memberCouponDTO);
            }
        }
    }

    /**
     * 渲染sku优惠信息
     *
     * @param tradeDTO        交易DTO
     * @param memberCouponDTO 优惠券DTO
     */
    private void renderSku(TradeDTO tradeDTO, MemberCouponDTO memberCouponDTO) {

        //计算优惠总金额
        Double countPrice = 0D;
        Map<String, Double> couponMap = memberCouponDTO.getSkuDetail();
        for (Double skuPrice : couponMap.values()) {
            countPrice = CurrencyUtil.add(countPrice, skuPrice);
        }

        //接收具体优惠券信息
        MemberCoupon coupon = memberCouponDTO.getMemberCoupon();
        //处理一个极端情况，如果优惠券满减金额大于订单金额
        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) && coupon.getPrice() > countPrice) {
            //将符合优惠券的金额写入，即最大扣减金额
            coupon.setPrice(countPrice);
        }

        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name())) {
            //减免现金，则按照商品价格计算 需要通过工具类进行优惠金额的分发，分发给每个商品
            this.renderCouponPrice(couponMap, tradeDTO, coupon, memberCouponDTO);
        } else {
            //打折券 直接计算
            this.renderCouponDiscount(couponMap, tradeDTO, coupon);
        }
    }

    /**
     * 减免现金，则按照商品价格计算 需要通过工具类进行优惠金额的分发，分发给每个商品
     *
     * @param couponMap       优惠券结算信息
     * @param tradeDTO        交易dto
     * @param coupon          优惠券信息
     * @param memberCouponDTO 用于计算优惠券结算详情
     */
    private void renderCouponPrice(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) {
        //分发优惠券
        promotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(),
                Boolean.TRUE.equals(coupon.getPlatformFlag()) ?
                        PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON);
        //如果是平台券 则需要计算商家承担比例
        if (Boolean.TRUE.equals(coupon.getPlatformFlag()) && coupon.getStoreCommission() > 0) {

            //循环所有优惠券
            for (String skuId : couponMap.keySet()) {

                for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
                    //写入平台优惠券承担比例
                    if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
                        //写入店铺承担比例
                        cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
                    }
                }
            }
        }
    }


    /**
     * 打折券计算
     *
     * @param couponMap 优惠券结算信息
     * @param tradeDTO  交易dto
     * @param coupon    优惠券信息
     */
    private void renderCouponDiscount(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon) {
        //循环所有优惠券
        for (String skuId : couponMap.keySet()) {

            // 循环购物车商品
            for (CartSkuVO item : tradeDTO.getSkuList()) {
                //如果id相等，则渲染商品价格信息
                if (item.getGoodsSku().getId().equals(skuId)) {

                    PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO();

                    // 打折金额=商品金额*折扣/10
                    Double discountCouponPrice = CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(),
                            CurrencyUtil.sub(1, CurrencyUtil.div(coupon.getDiscount(), 10, 3)));

                    //平台券则写入店铺承担优惠券比例
                    if (Boolean.TRUE.equals(coupon.getPlatformFlag())) {
                        priceDetailDTO.setSiteCouponPrice(discountCouponPrice);
                        priceDetailDTO.setSiteCouponPoint(coupon.getStoreCommission());
                    }
                    priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice));

                }
            }
        }
    }

}
