package com.bonus.core.marketing.v2.rule.price.handler.sumgive.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.common.utils.JacksonUtil;
import com.bonus.core.marketing.v2.model.MarketRuleRecord;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceResultOrderDTO;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceWalletDTO;
import com.bonus.core.marketing.v2.rule.price.handler.sumgive.dto.PriceSumGiveDTO;
import com.bonus.core.marketing.v2.rule.price.handler.sumgive.dto.PriceSumGiveItem;
import com.bonus.core.marketing.v2.rule.price.handler.sumgive.extension.PriceSumGiveHandlerExtension;
import com.bonus.core.marketing.v2.service.MarketRuleRangeService;
import com.bonus.core.marketing.v2.service.MarketRuleRecordService;
import com.bonus.core.marketing.v2.util.MarketUtil;
import com.bonus.core.marketing.vo.MarketRuleVO;
import com.bonus.core.order.common.constants.OrderTypeEnum;
import com.bonus.core.report.api.ReportOrderApi;
import com.bonus.core.report.api.dto.ReportCustConsumeSumDTO;
import com.bonus.core.report.statistics.order.basic.model.ReportOrderInfo;
import com.fasterxml.jackson.databind.JsonNode;
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.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DefaultSumGiveHandlerImpl implements PriceSumGiveHandlerExtension {
   private static final Logger log = LoggerFactory.getLogger(DefaultSumGiveHandlerImpl.class);
   @Autowired
   private MarketRuleRangeService rangeService;
   @Autowired
   private MarketRuleRecordService recordService;
   @Autowired
   private ReportOrderApi reportOrderApi;

   public void handle(RulePriceResultOrderDTO order, MarketRuleVO rule, List<RulePriceResultOrderDTO> orderResults) {
      PriceSumGiveDTO sumGiveDTO = (PriceSumGiveDTO)JSONObject.parseObject(rule.getRuleInfo(), PriceSumGiveDTO.class);
      List<ReportOrderInfo> orders = this.getHistoryOrders(order, (List)null);
      BigDecimal historyAmount = (BigDecimal)orders.stream().map(ReportOrderInfo::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
      log.info("【计价规则】历史金额：{}", historyAmount);
      BigDecimal nowAmount = this.getNowAmount((List)null, (List)null, orderResults);
      log.info("【计价规则】本次金额：{}", nowAmount);
      BigDecimal totalCount = historyAmount.add(nowAmount);
      List<PriceSumGiveItem> items = (List)sumGiveDTO.getItems().stream().sorted(Comparator.comparing(PriceSumGiveItem::getDoorAmount).reversed()).collect(Collectors.toList());
      Optional<PriceSumGiveItem> first = items.stream().filter((e) -> {
         return totalCount.compareTo(e.getDoorAmount()) >= 0;
      }).findFirst();
      if (!first.isPresent()) {
         log.info("【计价规则】未匹配到门槛金额");
      } else {
         PriceSumGiveItem item = (PriceSumGiveItem)first.get();
         List<MarketRuleRecord> records = this.recordService.getRuleRecordByRuleByEffectFlag(order.getCustId(), (LocalDate)null, (LocalDate)null, (List)null, CollUtil.newArrayList(new Long[]{rule.getRuleId()}), (Integer)null);
         Optional<MarketRuleRecord> optional = records.stream().filter((e) -> {
            PriceSumGiveItem recordItem = (PriceSumGiveItem) JacksonUtil.treeToValue(e.getExtInfo(), PriceSumGiveItem.class);
            return Objects.nonNull(recordItem) && Objects.nonNull(recordItem.getDoorAmount()) && recordItem.getDoorAmount().compareTo(item.getDoorAmount()) >= 0;
         }).findFirst();
         if (optional.isPresent()) {
            log.info("【计价规则】已经享受过此门槛金额赠送");
         } else {
            order.getWalletDetails().add(new RulePriceWalletDTO(item.getWalletId(), item.getGiveAmount(), AccTradeTypeEnum.RECHARGE_GIFT.getKey(), (JsonNode)null));
            order.getWalletDetails().add(new RulePriceWalletDTO(-1, order.getRealAmount(), AccTradeTypeEnum.CONSUME.getKey(), (JsonNode)null));
            order.setExtInfo(JacksonUtil.valueToTree(item));
            log.info("【计价规则】订单：{}", JacksonUtil.writeValueAsString(order));
         }
      }
   }

   protected BigDecimal getNowAmount(List<Integer> mealtimeTypeList, List<String> customDeviceList, List<RulePriceResultOrderDTO> orderResults) {
      return (BigDecimal)orderResults.stream().filter((e) -> {
         return (CollUtil.isEmpty(mealtimeTypeList) || CollUtil.contains(mealtimeTypeList, e.getMealtimeType())) && (CollUtil.isEmpty(customDeviceList) || CollUtil.contains(customDeviceList, MarketUtil.formatDeviceSn(e.getOrderType(), e.getCanteenId(), e.getStallId(), e.getDeviceSn()))) && OrderTypeEnum.isCanteenCategory(e.getOrderType());
      }).map(RulePriceResultOrderDTO::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
   }

   protected List<ReportOrderInfo> getHistoryOrders(RulePriceResultOrderDTO order, List<Integer> mealtimeTypeList) {
      List<Integer> orderTypes = (List)Arrays.stream(OrderTypeEnum.values()).map(OrderTypeEnum::getKey).filter(OrderTypeEnum::isCanteenCategory).collect(Collectors.toList());
      ReportCustConsumeSumDTO query = new ReportCustConsumeSumDTO();
      query.setCustId(order.getCustId());
      query.setMealtimeTypeList(mealtimeTypeList);
      query.setOrderTypeList(orderTypes);
      return (List)Optional.ofNullable(this.reportOrderApi.getCustConsumeSum(query)).orElse(new ArrayList());
   }

   protected boolean isValidOrder(List<String> customDeviceList, ReportOrderInfo e) {
      return CollUtil.isEmpty(customDeviceList) || CollUtil.contains(customDeviceList, MarketUtil.formatDeviceSn(e.getOrderType(), e.getCanteenId(), e.getStallId(), e.getMachineSn()));
   }
}
