package com.bonus.canteen.core.marketing.v2.rule.price.handler.discount.extension.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.bonus.canteen.core.marketing.v2.constants.MarketModuleTypeEnum;
import com.bonus.canteen.core.marketing.v2.model.MarketRule;
import com.bonus.canteen.core.marketing.v2.model.MarketRuleRecord;
import com.bonus.canteen.core.marketing.v2.rule.price.dto.RulePriceResultOrderDTO;
import com.bonus.canteen.core.marketing.v2.rule.price.handler.discount.dto.PriceDiscountDTO;
import com.bonus.canteen.core.marketing.v2.rule.price.handler.discount.extension.PriceDiscountHandlerExtension;
import com.bonus.canteen.core.marketing.v2.service.MarketRuleRecordService;
import com.bonus.canteen.core.marketing.v2.service.MarketRuleService;
import com.bonus.canteen.core.marketing.vo.MarketRuleVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class DefaultPriceDiscountHandlerImpl implements PriceDiscountHandlerExtension {
   private static final Logger log = LoggerFactory.getLogger(DefaultPriceDiscountHandlerImpl.class);
   @Autowired
   private MarketRuleRecordService recordService;
   @Autowired
   private MarketRuleService ruleService;

   public void handle(RulePriceResultOrderDTO order, MarketRuleVO rule, List<RulePriceResultOrderDTO> orderResults) {
      PriceDiscountDTO discountDTO = (PriceDiscountDTO)JSONObject.parseObject(rule.getRuleInfo(), PriceDiscountDTO.class);
      BigDecimal calAmount = order.getPayableAmount();
      BigDecimal noCalAmount = BigDecimal.ZERO;
      BigDecimal joinAmount = discountDTO.getJoinAmount();
      BigDecimal finalDiscountAmount;
      if (Objects.nonNull(joinAmount)) {
         List<MarketRule> rules = this.ruleService.listRuleByType(MarketModuleTypeEnum.RULE_PRICE.getKey(), rule.getRuleType());
         List<Long> ruleIds = (List)rules.stream().map(MarketRule::getRuleId).collect(Collectors.toList());
         List<MarketRuleRecord> records = this.recordService.getRuleRecordByRule(order.getCustId(), order.getOrderDate(), order.getOrderDate(), (List)null, ruleIds);
         finalDiscountAmount = (BigDecimal)records.stream().map(MarketRuleRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
         if (finalDiscountAmount.compareTo(joinAmount) < 0) {
            calAmount = NumberUtil.add(finalDiscountAmount, order.getPayableAmount()).compareTo(joinAmount) <= 0 ? order.getPayableAmount() : joinAmount.subtract(finalDiscountAmount);
            noCalAmount = order.getPayableAmount().subtract(calAmount);
         } else {
            calAmount = BigDecimal.ZERO;
            noCalAmount = order.getPayableAmount();
         }
      }

      BigDecimal ratio = this.getRatio(order, discountDTO, rule);
      BigDecimal realAmount = calAmount.multiply(ratio).setScale(0, RoundingMode.DOWN);
      BigDecimal discountAmount = calAmount.subtract(realAmount);
      log.info("calAmount================:{}", calAmount);
      log.info("realAmount================:{}", realAmount);
      log.info("discountAmount================:{}", discountAmount);
      finalDiscountAmount = discountAmount;
      BigDecimal finalRealAmount = realAmount;
      if (Objects.nonNull(discountDTO.getMaxAmount())) {
         BigDecimal maxDiscountAmount = discountDTO.getMaxAmount();
         log.info("maxDiscountAmount================:{}", maxDiscountAmount);
         if (discountAmount.abs().compareTo(maxDiscountAmount) > 0) {
            log.info("discountAmount.compareTo(0) ================:{}", discountAmount.compareTo(BigDecimal.ZERO));
            finalDiscountAmount = discountAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO.subtract(maxDiscountAmount) : maxDiscountAmount;
            finalRealAmount = discountAmount.compareTo(BigDecimal.ZERO) < 0 ? calAmount.add(maxDiscountAmount) : calAmount.subtract(maxDiscountAmount);
            log.info("finalDiscountAmount================:{}", finalDiscountAmount);
            log.info("finalRealAmount================:{}", finalRealAmount);
         }
      }

      log.info("finalDiscountAmount2================:{}", finalDiscountAmount);
      log.info("finalRealAmount2================:{}", finalRealAmount);
      order.setRealAmount(finalRealAmount.add(noCalAmount));
      order.setDiscountsAmount(finalDiscountAmount);
      log.info("resultOrder================:{}", JSONUtil.parseObj(order));
   }

   protected BigDecimal getRatio(RulePriceResultOrderDTO order, PriceDiscountDTO discountDTO, MarketRuleVO rule) {
      if (CollUtil.isEmpty(discountDTO.getItems())) {
         return BigDecimal.ONE;
      } else {
         log.info("折扣====：{}", JSONUtil.toJsonStr(discountDTO.getItems()));
         List<MarketRuleRecord> records = this.recordService.getRuleRecordByRule(order.getCustId(), order.getOrderDate(), order.getOrderDate(), CollUtil.newArrayList(new Integer[]{order.getMealtimeType()}), CollUtil.newArrayList(new Long[]{rule.getRuleId()}));
         log.info("历史订单条数====：{}", records.size());
         int count = records.size() + 1;
         return count >= discountDTO.getItems().size() ? (BigDecimal)CollUtil.getLast(discountDTO.getItems()) : (BigDecimal)discountDTO.getItems().get(records.size());
      }
   }
}
