package com.slodon.b2b2c.model.promotion;

import com.slodon.b2b2c.business.dto.OrderConfirmDTO;
import com.slodon.b2b2c.business.dto.OrderSubmitDTO;
import com.slodon.b2b2c.core.constant.PromotionConst;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.core.util.StringUtil;
import com.slodon.b2b2c.model.promotion.base.PromotionBaseModel;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

@Component
public class IntegralModel extends PromotionBaseModel {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 活动名称
     *
     * @return
     */
    @Override
    public String promotionName() {
        return "积分换购";
    }

    /**
     * 是否有扩展方法
     *
     * @return
     */
    @Override
    public Boolean specialOrder() {
        return false;
    }

    /**
     * 确认订单计算活动优惠
     *
     * @param promotionCartGroup 按照活动类型-活动id分组的购物车列表
     */
    @Override
    public void orderConfirmCalculationDiscount(OrderConfirmDTO.StoreCartGroup.PromotionCartGroup promotionCartGroup) {

    }

    /**
     * 提交订单计算活动优惠
     *
     * @param dto 拆单后的订单提交信息
     */
    @Override
    public void orderSubmitCalculationDiscount(OrderSubmitDTO dto) {
        if (StringUtil.isNullOrZero(dto.getIntegral())) {
            //未使用积分
            return;
        }
        //是否开启积分兑换
        if (!isPromotionAvailable("")) {
            throw new MallException("积分抵扣未开启");
        }
        //查询积分兑换比例,多少积分换1元（默认100积分换1元）
        String conversionRatio = stringRedisTemplate.opsForValue().get("integral_conversion_ratio");
        int rate = StringUtil.isEmpty(conversionRatio) ? 100 : Integer.parseInt(conversionRatio);

        BigDecimal totalIntegralCashAmount = new BigDecimal(dto.getIntegral()).divide(new BigDecimal(rate), 2, RoundingMode.DOWN);//此次积分抵扣金额，舍弃第三位小数
        dto.setIntegralCashAmount(totalIntegralCashAmount);

        BigDecimal goodsAmount = BigDecimal.ZERO;//用商品金额，判断积分是否满足使用条件、拆分到各个货品的基数
        List<OrderSubmitDTO.OrderInfo> orderInfoList = dto.getOrderInfoList();
        for (OrderSubmitDTO.OrderInfo info : orderInfoList) {
            goodsAmount = goodsAmount.add(info.getGoodsAmount());
        }

        //订单金额达到积分最低使用金额后，才可以使用使用积分抵扣现金
        String useLowestAmount = stringRedisTemplate.opsForValue().get("integral_use_lowest_amount");
        BigDecimal lowestAmount = StringUtil.isEmpty(useLowestAmount) ? goodsAmount : new BigDecimal(useLowestAmount);
        if (goodsAmount.compareTo(lowestAmount) < 0) {
            throw new MallException("订单金额未达到积分最低使用金额");
        }

        //最高抵扣金额,例如：商品金额为200元，最高抵扣上限为90%，则积分最多可抵扣180元
        String deductRate = stringRedisTemplate.opsForValue().get("integral_max_deduct_rate");
        int maxDeductRate = StringUtil.isEmpty(deductRate) || Integer.parseInt(deductRate) > 100 ? 100 : Integer.parseInt(deductRate);
        //此次抵扣金额必须小于最高抵扣金额
        AssertUtil.isTrue(totalIntegralCashAmount.compareTo(goodsAmount.multiply(new BigDecimal(maxDeductRate))) > 0,"积分使用失败，请重新选择");

        //将积分优惠分配到各个订单货品
        BigDecimal assignedMoney = new BigDecimal("0.00");//已分配的积分抵扣金额
        int assignedIntegral = 0;//已分配的积分数
        for (int i = 0, orderInfoListSize = orderInfoList.size(); i < orderInfoListSize; i++) {
            OrderSubmitDTO.OrderInfo orderInfo = orderInfoList.get(i);
            List<OrderSubmitDTO.OrderInfo.OrderProductInfo> orderProductInfoList = orderInfo.getOrderProductInfoList();
            for (int j = 0, orderProductInfoListSize = orderProductInfoList.size(); j < orderProductInfoListSize; j++) {
                OrderSubmitDTO.OrderInfo.OrderProductInfo orderProductInfo = orderProductInfoList.get(j);
                //构造活动信息
                OrderSubmitDTO.PromotionInfo promotionInfo = new OrderSubmitDTO.PromotionInfo();
                promotionInfo.setPromotionType(PromotionConst.PROMOTION_TYPE_401);
                promotionInfo.setPromotionId("0");
                promotionInfo.setPromotionName(this.promotionName());
                promotionInfo.setIsStore(false);
                if (i == orderInfoListSize - 1 && j == orderProductInfoListSize - 1) {
                    //最后一个订单货品，分配剩余金额
                    promotionInfo.setDiscount(totalIntegralCashAmount.subtract(assignedMoney));
                    orderProductInfo.setIntegral(dto.getIntegral() - assignedIntegral);
                    orderProductInfo.setIntegralCashAmount(totalIntegralCashAmount.subtract(assignedMoney));
                } else {
                    //不是最后一个订单货品，按比例分配
                    BigDecimal currentAssignedMoney = orderProductInfo.getProductPrice().multiply(new BigDecimal(orderProductInfo.getBuyNum()))//使用原价计算比例
                            .multiply(totalIntegralCashAmount)
                            .divide(goodsAmount, 2, RoundingMode.HALF_UP);//四舍五入
                    currentAssignedMoney = currentAssignedMoney.min(orderProductInfo.getMoneyAmount());//当前分配金额最大不能超过应付金额
                    int currentAssignedIntegral = currentAssignedMoney.multiply(new BigDecimal(rate)).intValue();//通过分配的金额计算分配的积分数量
                    promotionInfo.setDiscount(currentAssignedMoney);
                    orderProductInfo.setIntegral(currentAssignedIntegral);
                    orderProductInfo.setIntegralCashAmount(currentAssignedMoney);

                    //已分配金额累加
                    assignedMoney = assignedMoney.add(currentAssignedMoney);
                    assignedIntegral += currentAssignedIntegral;
                }
                //订单货品添加活动
                orderProductInfo.getPromotionInfoList().add(promotionInfo);
            }
        }

    }

    /**
     * 校验活动是否可用
     *
     * @param promotionId
     * @return
     */
    @Override
    public Boolean isPromotionAvailable(String promotionId) {
        return "1".equals(stringRedisTemplate.opsForValue().get("integral_cash_out_is_enable"));
    }

}
