package com.bonus.core.marketing.v2.rule.recharge.handler.fullgift.extension.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.bonus.core.account.v3.constants.AccTradeTypeEnum;
import com.bonus.core.marketing.util.EnumUtil;
import com.bonus.core.marketing.v2.rule.recharge.constants.RuleRechargeComputeTypeEnum;
import com.bonus.core.marketing.v2.rule.recharge.constants.RuleRechargeTypeEnum;
import com.bonus.core.marketing.v2.rule.recharge.dto.RuleRechargeResultDTO;
import com.bonus.core.marketing.v2.rule.recharge.dto.RuleRechargeWalletDTO;
import com.bonus.core.marketing.v2.rule.recharge.handler.fullgift.dto.RechargeGiftFullDTO;
import com.bonus.core.marketing.v2.rule.recharge.handler.fullgift.dto.RechargeGiftFullItemDTO;
import com.bonus.core.marketing.v2.rule.recharge.handler.fullgift.extension.RechargeFullGiftHandlerExtension;
import com.bonus.core.marketing.vo.MarketRuleVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class DefaultRechargeFullGiftHandlerImpl implements RechargeFullGiftHandlerExtension {
   private static final Logger log = LoggerFactory.getLogger(DefaultRechargeFullGiftHandlerImpl.class);

   @Override
   public void handle(RuleRechargeResultDTO resultDTO, MarketRuleVO ruleInfo) {
      RechargeGiftFullDTO rule = (RechargeGiftFullDTO)JSONObject.parseObject(ruleInfo.getRuleInfo(), RechargeGiftFullDTO.class);
      if (!CollUtil.isEmpty(rule.getItems())) {
         Integer rechargeType = rule.getRechargeType();
         RuleRechargeTypeEnum typeEnum = (RuleRechargeTypeEnum) EnumUtil.getEnumByKey(RuleRechargeTypeEnum.class, rechargeType);
         if (!Objects.isNull(typeEnum)) {
            switch (typeEnum) {
               case RECHARGE_TYPE_STEP:
                  this.step(resultDTO, rule.getItems());
                  break;
               case RECHARGE_TYPE_CYCLE:
                  this.cycle(resultDTO, rule.getItems());
                  break;
               default:
                  this.fixed(resultDTO, rule.getItems());
            }

         }
      }
   }

   protected void fixed(RuleRechargeResultDTO resultDTO, List<RechargeGiftFullItemDTO> items) {
      RechargeGiftFullItemDTO itemDTO = (RechargeGiftFullItemDTO)items.get(0);
      BigDecimal doorAmount = itemDTO.getDoorAmount();
      if (resultDTO.getAmount().compareTo(doorAmount) >= 0) {
         this.addWalletDetail(resultDTO, itemDTO);
      }
   }

   protected void step(RuleRechargeResultDTO resultDTO, List<RechargeGiftFullItemDTO> items) {
      BigDecimal amount = resultDTO.getAmount();
      List<RechargeGiftFullItemDTO> sortItems = (List)items.stream().sorted(Comparator.comparing(RechargeGiftFullItemDTO::getDoorAmount).reversed()).collect(Collectors.toList());
      sortItems.stream().filter((e) -> {
         return amount.compareTo(e.getDoorAmount()) >= 0;
      }).findFirst().ifPresent((firstStep) -> {
         this.addWalletDetail(resultDTO, firstStep);
      });
   }

   protected void cycle(RuleRechargeResultDTO resultDTO, List<RechargeGiftFullItemDTO> items) {
      RechargeGiftFullItemDTO item = (RechargeGiftFullItemDTO)items.get(0);
      Integer computeType = item.getComputeType();
      BigDecimal amount = resultDTO.getAmount();
      BigDecimal doorAmount = item.getDoorAmount();
      BigDecimal discount = item.getDiscount();
      BigDecimal times = amount.divide(doorAmount, 0, RoundingMode.DOWN);
      BigDecimal giftAmount = Objects.equals(RuleRechargeComputeTypeEnum.COMPUTE_TYPE_AMOUNT.getKey(), computeType) ? discount.multiply(times) : doorAmount.multiply(times).multiply(discount).setScale(0, RoundingMode.HALF_UP);
      if (giftAmount.compareTo(BigDecimal.ZERO) > 0) {
         resultDTO.setActualAmount(resultDTO.getActualAmount().add(giftAmount));
         resultDTO.getWalletDetails().add((new RuleRechargeWalletDTO()).setWalletId(item.getWalletId()).setAmount(giftAmount).setTradeType(AccTradeTypeEnum.RECHARGE_GIFT.getKey()));
      }

   }

   protected void addWalletDetail(RuleRechargeResultDTO resultDTO, RechargeGiftFullItemDTO item) {
      Integer giftType = item.getComputeType();
      BigDecimal discount = item.getDiscount();
      Integer walletId = item.getWalletId();
      BigDecimal giftAmount = RuleRechargeComputeTypeEnum.COMPUTE_TYPE_AMOUNT.getKey().equals(giftType) ? discount : resultDTO.getAmount().multiply(discount).setScale(0, RoundingMode.UP);
      if (giftAmount.compareTo(BigDecimal.ZERO) > 0) {
         resultDTO.setActualAmount(resultDTO.getActualAmount().add(giftAmount));
         resultDTO.getWalletDetails().add((new RuleRechargeWalletDTO()).setWalletId(walletId).setAmount(giftAmount).setTradeType(AccTradeTypeEnum.RECHARGE_GIFT.getKey()));
      }

   }
}
