package com.bonus.canteen.core.marketing.coupon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.canteen.core.marketing.coupon.dto.GroupByCouponStateDto;
import com.bonus.canteen.core.marketing.coupon.service.MktCouponTmplBackService;
import com.bonus.canteen.core.marketing.coupon.dto.GroupCuponDto;
import com.bonus.canteen.core.marketing.coupon.vo.MktCouponMobileVO;
import com.bonus.canteen.core.marketing.coupon.vo.MktCouponTmplBackVO;
import com.bonus.canteen.core.marketing.coupon.vo.MktGroupVo;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.canteen.core.allocation.canteen.mapper.AllocCanteenMapper;
import com.bonus.canteen.core.marketing.coupon.constants.MktCouponStateEnum;
import com.bonus.canteen.core.marketing.coupon.constants.MktCouponTypeEnum;
import com.bonus.canteen.core.marketing.coupon.mapper.MktCouponMapper;
import com.bonus.canteen.core.marketing.coupon.mapper.MktCouponTmplDetlBackMapper;
import com.bonus.canteen.core.marketing.coupon.model.MktCoupon;
import com.bonus.canteen.core.marketing.coupon.model.MktCouponMacPayModel;
import com.bonus.canteen.core.marketing.coupon.model.MktCouponPayModel;
import com.bonus.canteen.core.marketing.coupon.model.MktCouponTmplDetlBack;
import com.bonus.canteen.core.marketing.coupon.param.MktCouponMobileUsableParam;
import com.bonus.canteen.core.marketing.coupon.service.MktCouponService;
import com.bonus.canteen.core.marketing.coupon.vo.MktCouponMobileUsableVO;
import com.bonus.canteen.core.order.common.constants.OrderTypeEnum;
import com.bonus.common.houqin.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

@Service
public class MktCouponServiceImpl extends ServiceImpl<MktCouponMapper, MktCoupon> implements MktCouponService {
   private static final Logger log = LoggerFactory.getLogger(MktCouponServiceImpl.class);
   @Autowired
   @Lazy
   private MktCouponTmplBackService mktCouponTmplBackService;
   @Resource
   private MktCouponTmplDetlBackMapper mktCouponTmplDetlBackMapper;
   @Autowired
   @Lazy
   private AllocCanteenMapper allocCanteenMapper;

   public List<MktCoupon> listUsableElecCouponByCustId(Long custId) {
      List<MktCoupon> couponList = this.list(Wrappers
              .lambdaQuery(MktCoupon.class).eq(MktCoupon::getCustId, custId)
              .eq(MktCoupon::getCouponType, MktCouponTypeEnum.ELECTRON_COUPON.getKey())
              .in(MktCoupon::getCouponState, MktCouponStateEnum.getNoUseState()).orderByDesc(MktCoupon::getCrtime));
      return CollUtil.isEmpty(couponList) ? new ArrayList<>() : couponList;
   }

   public MktGroupVo listElecMobileGroup(GroupCuponDto groupCuponDto) {
      MktGroupVo mktGroupVo = new MktGroupVo();
      List<GroupByCouponStateDto> groupByCouponState = ((MktCouponMapper)this.baseMapper).getGroupByCouponState(groupCuponDto.getCustId());
      mktGroupVo.putNum(groupByCouponState);
      Page<MktCoupon> page = new Page(groupCuponDto.getCurrent(), groupCuponDto.getSize());
      this.page(page, Wrappers.lambdaQuery(MktCoupon.class).eq(MktCoupon::getCustId, groupCuponDto.getCustId())
              .eq(MktCoupon::getCouponState, groupCuponDto.getCouponState())
              .eq(MktCoupon::getCouponType, MktCouponTypeEnum.ELECTRON_COUPON.getKey()).orderByDesc(MktCoupon::getId));
      List<MktCouponMobileVO> resultMobileVOList = new ArrayList();
      Iterator var6 = page.getRecords().iterator();

      while(var6.hasNext()) {
         MktCoupon mktCoupon = (MktCoupon)var6.next();
         MktCouponTmplBackVO tmplBackVO = this.mktCouponTmplBackService.getBackRelationName(mktCoupon.getBackId(), MktCouponTypeEnum.ELECTRON_COUPON);
         MktCouponMobileVO mobileVO = new MktCouponMobileVO();
         BeanUtils.copyProperties(mktCoupon, mobileVO);
         mobileVO.setCanteenNameStr(tmplBackVO.getCanteenNameStr());
         mobileVO.setShopstallNameStr(tmplBackVO.getShopstallNameStr());
         mobileVO.setIntervalNameStr(tmplBackVO.getIntervalNameStr());
         resultMobileVOList.add(mobileVO);
      }

      Page<MktCouponMobileVO> result = (Page)BeanUtil.copyProperties(page, Page.class, new String[0]);
      result.setRecords(resultMobileVOList);
      mktGroupVo.setPage(result);
      return mktGroupVo;
   }

   public List<MktCouponMobileUsableVO> listElecMobileUsable(MktCouponMobileUsableParam param) {
      List<MktCoupon> couponList = this.listUsableElecCouponByCustId(param.getCustId());
      Long canteenId = (Long)param.getCanteenIdSet().stream().findFirst().orElse(null);
      Long areaId = this.allocCanteenMapper.getAreaId(canteenId);
      List<MktCoupon> resultCouponList = new ArrayList<>();
      Iterator var6 = couponList.iterator();

      while(true) {
         MktCoupon coupon;
         HashSet shopstallIdSet;
         HashSet intervalIdSet;
         do {
            HashSet canteenIdSet;
            do {
               HashSet areaIdSet;
               do {
                  label39:
                  do {
                     while(var6.hasNext()) {
                        coupon = (MktCoupon)var6.next();
                        List<MktCouponTmplDetlBack> detlBackList = this.mktCouponTmplDetlBackMapper.listByBackId(coupon.getBackId());
                        if (!CollUtil.isEmpty(detlBackList) && !detlBackList.contains((Object)null)) {
                           canteenIdSet = new HashSet();
                           shopstallIdSet = new HashSet();
                           intervalIdSet = new HashSet();
                           areaIdSet = new HashSet();
                           this.detlBackDataHandle(detlBackList, canteenIdSet, shopstallIdSet, intervalIdSet, areaIdSet);
                           continue label39;
                        }

                        resultCouponList.add(coupon);
                     }

                     if (CollUtil.isEmpty(resultCouponList)) {
                        return new ArrayList();
                     }

                     return BeanUtil.copyToList(resultCouponList, MktCouponMobileUsableVO.class);
                  } while(CollUtil.isNotEmpty(areaIdSet) && !areaIdSet.contains(areaId));
               } while(CollUtil.isNotEmpty(canteenIdSet) && !canteenIdSet.containsAll(param.getCanteenIdSet()));
            } while(CollUtil.isNotEmpty(shopstallIdSet) && !shopstallIdSet.containsAll(param.getShopstallIdSet()));
         } while(CollUtil.isNotEmpty(intervalIdSet) && !intervalIdSet.containsAll(param.getIntervalIdSet()));

         resultCouponList.add(coupon);
      }
   }

   public void detlBackDataHandle(List<MktCouponTmplDetlBack> detlBackList, Set<Long> canteenIdSet, Set<Long> stallIdSet, Set<Long> mealtimeTypeSet, Set<Long> areaIdSet) {
      Iterator var6 = detlBackList.iterator();

      while(var6.hasNext()) {
         MktCouponTmplDetlBack detlBack = (MktCouponTmplDetlBack)var6.next();
         if (ObjectUtil.isNotNull(detlBack.getCanteenId())) {
            canteenIdSet.add(detlBack.getCanteenId());
         }

         if (ObjectUtil.isNotNull(detlBack.getShopstallId())) {
            stallIdSet.add(detlBack.getShopstallId());
         }

         if (ObjectUtil.isNotNull(detlBack.getIntervalId())) {
            mealtimeTypeSet.add(detlBack.getIntervalId());
         }

         if (ObjectUtil.isNotNull(detlBack.getAreaId())) {
            areaIdSet.add(detlBack.getAreaId());
         }
      }
   }

   public MktCouponPayModel getCouponAmountForMacPay(MktCouponMacPayModel macPayModel) {
      if (!OrderTypeEnum.isCanteenCategory(macPayModel.getOrderType())) {
         return null;
      } else {
         Long areaId = this.allocCanteenMapper.getAreaId((Long)macPayModel.getCanteenIds().stream().findAny().orElse(null));
         if (ObjectUtil.isNotNull(macPayModel.getCouponNum())) {
            MktCoupon mktCoupon = this.getCouponByNum(macPayModel.getCouponNum());
            this.checkUsableCoupon(mktCoupon);
            this.checkCouponRuleLimit(macPayModel.getCouponNum(), mktCoupon.getBackId(), macPayModel.getCanteenIds(), macPayModel.getStallIds(), macPayModel.getMealtimeIds(), CollUtil.newHashSet(new Long[]{areaId}));
            return new MktCouponPayModel(mktCoupon.getCustId(), macPayModel.getCouponNum(), mktCoupon.getCouponType(), mktCoupon.getCouponAmount());
         } else if (ObjectUtil.isNotNull(macPayModel.getCustId())) {
            List<MktCoupon> mktCouponList = this.list(Wrappers
                    .lambdaQuery(MktCoupon.class).eq(MktCoupon::getCouponState, MktCouponStateEnum.NO_USE.getKey())
                    .eq(MktCoupon::getCustId, macPayModel.getCustId()).eq(MktCoupon::getCouponType, macPayModel.getCouponType())
                    .orderByAsc(MktCoupon::getCouponAmount, MktCoupon::getEffectDateEnd));
            if (CollUtil.isEmpty(mktCouponList)) {
               return null;
            } else {
               this.filterCouponRuleLimit(mktCouponList, macPayModel.getCanteenIds(), macPayModel.getStallIds(), macPayModel.getMealtimeIds(), CollUtil.newHashSet(new Long[]{areaId}));
               if (CollUtil.isEmpty(mktCouponList)) {
                  return null;
               } else {
                  BigDecimal orderAmount = macPayModel.getOrderAmount().divide(new BigDecimal("100"));
                  Iterator var5 = mktCouponList.iterator();

                  MktCoupon mktCoupon;
                  do {
                     if (!var5.hasNext()) {
                        mktCoupon = mktCouponList.get(mktCouponList.size() - 1);
                        return new MktCouponPayModel(mktCoupon.getCustId(), mktCoupon.getCouponNum(), mktCoupon.getCouponType(), mktCoupon.getCouponAmount());
                     }

                     mktCoupon = (MktCoupon)var5.next();
                     Logger var10000 = log;
                     String var10001 = String.valueOf(orderAmount);
                     var10000.info("订单金额:" + var10001 + ",餐券金额:" + String.valueOf(mktCoupon.getCouponAmount()) + ",餐券id:" + mktCoupon.getCouponId());
                  } while(orderAmount.compareTo(mktCoupon.getCouponAmount()) > 0);

                  return new MktCouponPayModel(mktCoupon.getCustId(), mktCoupon.getCouponNum(), mktCoupon.getCouponType(), mktCoupon.getCouponAmount());
               }
            }
         } else {
            return null;
         }
      }
   }

   private MktCoupon getCouponByNum(Long couponNum) {
      MktCoupon mktCoupon = this.getOne(Wrappers.lambdaQuery(MktCoupon.class)
              .eq(MktCoupon::getCouponNum, couponNum));
      if (ObjectUtil.isNull(mktCoupon)) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_get_info", new Object[0]));
      } else {
         return mktCoupon;
      }
   }

   private void checkUsableCoupon(MktCoupon mktCoupon) {
      if (LocalDate.now().isBefore(mktCoupon.getEffectDateStart())) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_today_vaild", new Object[0]));
      } else if (LocalDate.now().isAfter(mktCoupon.getEffectDateEnd())) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_vaild_overdue", new Object[0]));
      } else if (MktCouponStateEnum.NO_EFFECT.getKey().equals(mktCoupon.getCouponState())) {
         this.update(Wrappers.lambdaUpdate(MktCoupon.class)
                 .set(MktCoupon::getCouponState, MktCouponStateEnum.NO_USE.getKey())
                 .eq(MktCoupon::getCouponId, mktCoupon.getCouponId()));
      } else if (MktCouponStateEnum.ALREADY_USE.getKey().equals(mktCoupon.getCouponState())) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_vaild_status", new Object[0]));
      } else if (MktCouponStateEnum.ALREADY_OVERDUE.getKey().equals(mktCoupon.getCouponState())) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_vaild_overdue", new Object[0]));
      } else if (MktCouponStateEnum.ALREADY_NULLIFY.getKey().equals(mktCoupon.getCouponState())) {
         throw new ServiceException(I18n.getMessage("mkt_coupon_vaild_invalid", new Object[0]));
      }
   }

   public void checkCouponRuleLimit(Long couponNum, Long backId, Set<Long> canteenId, Set<Long> stallId,
                                    Set<Long> mealtimeType, Set<Long> areaIds) {
      List<MktCouponTmplDetlBack> detlBackList = this.mktCouponTmplDetlBackMapper.listByBackId(backId);
      if (!CollUtil.isEmpty(detlBackList) && !detlBackList.contains((Object)null)) {
         Set<Long> canteenIdSet = new HashSet();
         Set<Long> stallIdSet = new HashSet();
         Set<Long> mealtimeIdSet = new HashSet();
         Set<Long> areaIdSet = new HashSet();
         this.detlBackDataHandle(detlBackList, canteenIdSet, stallIdSet, mealtimeIdSet, areaIdSet);
         if (CollUtil.isNotEmpty(areaIdSet) && !areaIdSet.containsAll(areaIds)) {
            throw new ServiceException(I18n.getMessage("mkt_coupon_area", new Object[]{couponNum}));
         } else if (CollUtil.isNotEmpty(canteenIdSet) && !canteenIdSet.containsAll(canteenId)) {
            throw new ServiceException(I18n.getMessage("mkt_coupon_canteen", new Object[]{couponNum}));
         } else if (CollUtil.isNotEmpty(stallIdSet) && !stallIdSet.containsAll(stallId)) {
            throw new ServiceException(I18n.getMessage("mkt_coupon_dining", new Object[]{couponNum}));
         } else if (CollUtil.isNotEmpty(mealtimeIdSet) && !mealtimeIdSet.containsAll(mealtimeType)) {
            throw new ServiceException(I18n.getMessage("mkt_coupon_meal_time", new Object[]{couponNum}));
         }
      }
   }

   private void filterCouponRuleLimit(List<MktCoupon> mktCouponList, Set<Long> canteenId, Set<Long> stallId, Set<Long> mealtimeId,
                                      Set<Long> areaId) {
      Iterator<MktCoupon> it = mktCouponList.iterator();

      while(true) {
         while(true) {
            HashSet canteenIdSet;
            HashSet stallIdSet;
            HashSet mealtimeIdSet;
            HashSet areaIdSet;
            List detlBackList;
            do {
               do {
                  if (!it.hasNext()) {
                     return;
                  }

                  MktCoupon mktCoupon = (MktCoupon)it.next();
                  canteenIdSet = new HashSet();
                  stallIdSet = new HashSet();
                  mealtimeIdSet = new HashSet();
                  areaIdSet = new HashSet();
                  detlBackList = this.mktCouponTmplDetlBackMapper.listByBackId(mktCoupon.getBackId());
               } while(CollUtil.isEmpty(detlBackList));
            } while(detlBackList.contains((Object)null));

            this.detlBackDataHandle(detlBackList, canteenIdSet, stallIdSet, mealtimeIdSet, areaIdSet);
            if (CollUtil.isNotEmpty(areaIdSet) && !areaIdSet.containsAll(areaId)) {
               it.remove();
            } else if (CollUtil.isNotEmpty(canteenIdSet) && !canteenIdSet.containsAll(canteenId)) {
               it.remove();
            } else if (CollUtil.isNotEmpty(stallIdSet) && !stallIdSet.containsAll(stallId)) {
               it.remove();
            } else if (CollUtil.isNotEmpty(mealtimeIdSet) && !mealtimeIdSet.containsAll(mealtimeId)) {
               it.remove();
            }
         }
      }
   }

}
