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

import com.alibaba.fastjson.JSONObject;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.core.marketing.v2.constants.MarketRangeTypeEnum;
import com.bonus.core.marketing.v2.constants.MarketSceneTypeEnum;
import com.bonus.core.marketing.v2.model.MarketRuleRange;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceLimitDTO;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceResultOrderDTO;
import com.bonus.core.marketing.v2.rule.price.handler.limitsumamount.dto.PriceLimitSumAmountDTO;
import com.bonus.core.marketing.v2.rule.price.handler.limitsumamount.extension.PriceLimitSumAmountHandlerExtension;
import com.bonus.core.marketing.v2.service.MarketRuleRangeService;
import com.bonus.core.marketing.v2.util.MarketUtil;
import com.bonus.core.marketing.vo.MarketRuleVO;
import com.bonus.core.order.api.OrderMarketingApi;
import com.bonus.core.order.common.model.OrderInfo;
import com.bonus.i18n.I18n;
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.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class DefaultPriceLimitSumAmountHandlerImpl implements PriceLimitSumAmountHandlerExtension {
   private static final Logger log = LoggerFactory.getLogger(DefaultPriceLimitSumAmountHandlerImpl.class);
   @Autowired
   private MarketRuleRangeService rangeService;
   @Autowired
   private OrderMarketingApi orderMarketingApi;

   public void handle(RulePriceResultOrderDTO order, MarketRuleVO rule, List<RulePriceResultOrderDTO> orderResults) {
      PriceLimitSumAmountDTO item = (PriceLimitSumAmountDTO)JSONObject.parseObject(rule.getRuleInfo(), PriceLimitSumAmountDTO.class);
      List<MarketRuleRange> rangeList = this.rangeService.getRangeByRuleId(rule.getRuleId());
      List<Integer> mealtimeTypeList = this.rangeService.filterRangeDetailByType(rangeList, MarketRangeTypeEnum.RANGE_MEALTIME);
      List<OrderInfo> orders = this.getOrders(order, item.getLimitType(), mealtimeTypeList, rule.getSceneType());
      List<String> customDeviceList = this.rangeService.filterRangeDetailByType(rangeList, MarketRangeTypeEnum.RANGE_DEVICE);
      BigDecimal oldAmount = (BigDecimal)orders.stream().filter((e) -> {
         return MarketUtil.isValidOrder(customDeviceList, e);
      }).map(OrderInfo::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
      BigDecimal nowAmount = this.getNowTradeCount(order, mealtimeTypeList, customDeviceList, item.getLimitType(), orderResults);
      BigDecimal totalCount = oldAmount.add(nowAmount);
      if (totalCount.compareTo(item.getMaxAmount()) > 0) {
         throw new ServiceException(I18n.getMessage("market_price_over_max_amount", new Object[0]));
      }
   }

   protected BigDecimal getNowTradeCount(RulePriceResultOrderDTO order, List<Integer> mealtimeTypeList, List<String> customDeviceList, Integer limitType, List<RulePriceResultOrderDTO> orderResults) {
      return (BigDecimal)MarketUtil.getNowTrade(order, mealtimeTypeList, customDeviceList, limitType, orderResults).stream().map(RulePriceResultOrderDTO::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
   }

   protected List<OrderInfo> getOrders(RulePriceResultOrderDTO order, Integer limitType, List<Integer> mealtimeTypeList, Integer sceneType) {
      RulePriceLimitDTO limitDTO = new RulePriceLimitDTO(order, limitType, mealtimeTypeList);
      List<Integer> orderTypes = MarketSceneTypeEnum.getOrderTypeBySceneType(sceneType);
      return (List)Optional.ofNullable(this.orderMarketingApi.listOrder(order.getCustId(), limitDTO.getBeginDate(), limitDTO.getEndDate(), limitDTO.getMealtimeTypeList(), orderTypes)).orElse(new ArrayList());
   }
}
