package com.yami.shop.coupon.api.util;

import cn.hutool.core.collection.CollectionUtil;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.bean.app.dto.ProductItemDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.enums.CouponProdType;
import com.yami.shop.bean.enums.CouponType;
import com.yami.shop.common.util.Arith;
import org.apache.commons.collections.CollectionUtils;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 协助优惠券进行选择
 * @author LGH
 */
public class ChooseCouponHelper {
    /**
     * 购物项
     */
    private List<ShopCartItemDto> shopCartItems;
    /**
     * 含有的优惠券列表
     */
    private List<CouponOrderDto> shopCoupons;
    /**
     * 选中的优惠券id
     */
    private List<Long> couponIds;

    /**
     * 用户是否选中优惠券
     */
    private Integer userChangeCoupon;
    /**
     * 选中的优惠券
     */
    private CouponOrderDto chooseCoupon;

    /**
     * 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
     */
    private double prodCanUseCouponActualTotal;

    /**
     * 优惠金额
     */
    private double couponReduce;

    /**
     * 优惠券在订单中的优惠金额
     */
    private double couponInOrderAmount;

    public ChooseCouponHelper(List<ShopCartItemDto> shopCartItems, List<CouponOrderDto> shopCoupons, List<Long> couponIds, Integer userChangeCoupon) {
        this.shopCartItems = shopCartItems;
        this.shopCoupons = shopCoupons;
        this.couponIds = couponIds;
        this.userChangeCoupon = userChangeCoupon;
    }

    public CouponOrderDto getChooseCoupon() {
        return chooseCoupon;
    }


    public double getCouponReduce() {
        return this.couponReduce;
    }

    public ChooseCouponHelper invoke() {
        // 没有平台优惠券直接返回
        if(CollectionUtils.isEmpty(shopCartItems)){
            return this;
        }


        // 用户选中的关于该店铺的优惠券，一家店只能选择一张优惠券
        chooseCoupon = null;

        // 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
        prodCanUseCouponActualTotal = 0.0;
        Date now = new Date();
        for (CouponOrderDto shopCoupon : shopCoupons) {
            if (shopCoupon.getStartTime().getTime() > now.getTime() && shopCoupon.getEndTime().getTime() < now.getTime()) {
                continue;
            }
            // 该优惠券关联的商品id
            List<Long> prodIds = shopCoupon.getProdIds();
            // 可用优惠券的商品实际金额（商品实际金额 - 商品分摊金额）
            prodCanUseCouponActualTotal = 0.0;
            for (ShopCartItemDto shopCartItem : shopCartItems) {
                shopCartItem.setIsShareReduce(0);
                // 该商品是否在该优惠券可用
                boolean isCouponsProd = isCouponsProd(shopCartItem.getProdId(), prodIds, shopCoupon.getSuitableProdType());
                if (isCouponsProd) {
                    shopCartItem.setIsShareReduce(1);
                    prodCanUseCouponActualTotal = Arith.add(prodCanUseCouponActualTotal, shopCartItem.getActualTotal());
                    // 向优惠券添加该订单含有的，可用该优惠券的商品id
                    shopCoupon.getChooseProdIds().add(shopCartItem.getProdId());
                }
            }
            Date date = new Date();
            // 如果该商品实际总金额大于等于优惠券最低使用金额，并且开始时间大于优惠券的使用时间，则优惠券可用
            if (prodCanUseCouponActualTotal >= shopCoupon.getCashCondition()  && shopCoupon.getStartTime().getTime() < date.getTime()) {
                // 将优惠券标记为可用状态
                shopCoupon.setCanUse(true);
                // 聚合 用户选中的关于该店铺的优惠券
                if (CollectionUtil.isNotEmpty(couponIds)) {
                    for (Long couponId : couponIds) {
                        if (Objects.equals(couponId, shopCoupon.getCouponId())) {
                            chooseCoupon = shopCoupon;
                        }
                    }
                }
                // 如果用户没有选择优惠券，系统默认选择一张可用优惠券
                if (chooseCoupon == null && !Objects.equals(userChangeCoupon, 1)) {
                    chooseCoupon = shopCoupon;
                }
            }
        }
        if (chooseCoupon != null) {
            chooseCoupon.setChoose(true);
            // 计算优惠券优惠金额
            calculateCouponReduce();
            // 设置分摊优惠金额
            setShareReduce();
        }
        return this;
    }

    /**
     * 判断某个商品是否在此优惠券中
     *
     * @param prodId         在该店铺中的商品商品id
     * @param couponProdIds  优惠券关联的商品id
     * @param couponProdType 优惠券适用商品类型
     * @return 商品是否在此优惠券中
     */
    private boolean isCouponsProd(Long prodId, List<Long> couponProdIds, Integer couponProdType) {

        if (CouponProdType.ALL.value().equals(couponProdType)) {
            return true;
        }
        if (CouponProdType.PROD_IN.value().equals(couponProdType)) {
            if (CollectionUtil.isEmpty(couponProdIds)) {
                return false;
            }
            for (Long couponProdId : couponProdIds) {
                if (Objects.equals(couponProdId, prodId)) {
                    return true;
                }
            }
            return false;
        }

        if (CouponProdType.PROD_NO_IN.value().equals(couponProdType)) {
            if (CollectionUtil.isEmpty(couponProdIds)) {
                return true;
            }
            for (Long couponProdId : couponProdIds) {
                if (Objects.equals(couponProdId, prodId)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }


    /**
     * 计算优惠金额
     */
    private void calculateCouponReduce() {
        couponReduce = 0.0;
        couponInOrderAmount = 0.0;
        // 代金券
        if (CouponType.C2M.value().equals(chooseCoupon.getCouponType())) {
            couponInOrderAmount = chooseCoupon.getReduceAmount();
        }
        // 折扣券
        if (CouponType.C2D.value().equals(chooseCoupon.getCouponType())) {
//            couponInOrderAmount = Arith.sub(prodCanUseCouponActualTotal, Arith.div(Arith.mul(prodCanUseCouponActualTotal, chooseCoupon.getCouponDiscount()), 10));
            couponInOrderAmount = Arith.round(Arith.sub(prodCanUseCouponActualTotal, Arith.div(Arith.mul(prodCanUseCouponActualTotal,
                    chooseCoupon.getCouponDiscount()), 10)),2);
            chooseCoupon.setReduceAmount(couponInOrderAmount);
        }
        couponReduce = Arith.add(couponReduce, couponInOrderAmount);
    }

    /**
     * 设置分摊优惠金额
     */
    private void setShareReduce() {
        double sumReduce = 0.0;
//        for (ShopCartItemDto shopCartItem : shopCartItems) {
        shopCartItems = shopCartItems.stream().sorted(Comparator.comparing(ProductItemDto::getActualTotal)).collect(Collectors.toList());
        for (int i = 0; i < shopCartItems.size(); i++) {
            ShopCartItemDto shopCartItem = shopCartItems.get(i);
            double shareReduce = 0.0;
            if (shopCartItem.getIsShareReduce() == 1) {
                shareReduce = Arith.round(Arith.mul(couponInOrderAmount, Arith.div(shopCartItem.getActualTotal(), prodCanUseCouponActualTotal, 10)),2);
            } else {
                shareReduce = 0.0;
            }
            // 分摊的优惠金额 不能大于商品金额
            double minShareReduce = Math.min(shareReduce, shopCartItem.getProductTotalAmount());
            //如果是最后一项，直接将剩余的优惠金额赋值给他
            if(i + 1 >= shopCartItems.size()) {
                minShareReduce =  Math.min(Arith.sub(couponReduce,sumReduce),shopCartItem.getProductTotalAmount());
            }
            if (Objects.equals(chooseCoupon.getShopId(), 0L)) {
                // 平台分摊的每一个购物项优惠金额
                shopCartItem.setPlatformShareReduce(Arith.add(shopCartItem.getPlatformShareReduce(),minShareReduce));
            } else {
                // 商家分摊的每一个购物项优惠金额
                shopCartItem.setShareReduce(Arith.add(shopCartItem.getShareReduce(),minShareReduce));
            }
            shopCartItem.setActualTotal(Arith.sub(shopCartItem.getActualTotal(), minShareReduce));
            sumReduce = Arith.add(minShareReduce,sumReduce);
        }
    }
}
