package com.bonus.canteen.core.pay.common.business;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.houqin.constant.RetCodeEnum;
import com.bonus.canteen.core.account.v4.constant.CardStatusEnum;
import com.bonus.canteen.core.allocation.alloc.model.AllocPayModel;
import com.bonus.canteen.core.allocation.api.AllocMetadataApi;
import com.bonus.canteen.core.common.constant.NuclearModeEnum;
import com.bonus.canteen.core.common.utils.LeCodeUtil;
import com.bonus.canteen.core.common.utils.LogUtil;
import com.bonus.canteen.core.customer.api.CustInfoApi;
import com.bonus.canteen.core.customer.dto.CustPayDTO;
import com.bonus.canteen.core.customer.vo.CustPayVO;
import com.bonus.canteen.core.order.deprecated.dto.OrdLeCodeDTO;
import com.bonus.canteen.core.order.utils.LeNumUtil;
import com.bonus.canteen.core.pay.common.constants.LeRetCodeEnum;
import com.bonus.canteen.core.pay.common.constants.PayChannelEnum;
import com.bonus.canteen.core.pay.common.constants.PayChannelSelectEnum;
import com.bonus.canteen.core.pay.common.service.PayChannelSelectService;
import com.bonus.canteen.core.pay.common.service.PayService;
import com.bonus.canteen.core.pay.common.vo.PayChannelSelectDTO;
import com.bonus.canteen.core.pay.common.vo.PayChannelSelectResultVO;
import com.bonus.canteen.core.pay.custom.PayCustomBusiness;
import com.bonus.common.houqin.i18n.I18n;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

@Component
public class ChannelBusiness {
   private static final Logger log = LoggerFactory.getLogger(ChannelBusiness.class);
   @Resource
   @Lazy
   protected PayChannelSelectService payChannelSelectService;
   @Resource
   @Lazy
   protected PayCustomBusiness payCustomBusiness;
   @Lazy
   @Autowired
   protected AllocMetadataApi allocMetadataApi;
   @Lazy
   @Autowired
   protected CustInfoApi custInfoApi;
   @Lazy
   @Autowired
   protected BeanFactory beanFactory;

   @Autowired
   RedissonClient redissonClient;


   public PayChannelSelectResultVO payChannelSelect(PayChannelSelectEnum selectType, PayChannelSelectDTO payChannelSelectDTO) {
      LogUtil.info("[支付渠道判断]入参", selectType, payChannelSelectDTO);
      PayChannelSelectResultVO resultVO = this.payCustomBusiness.willPayChannelSelectV2(selectType, payChannelSelectDTO);
      if (resultVO != null) {
         this.payCustomBusiness.didPayChannelSelectV2(selectType, payChannelSelectDTO, resultVO);
         LogUtil.info("[支付渠道判断]结果", resultVO);
         return resultVO;
      } else {
         AllocPayModel canteenPayModel = this.allocMetadataApi.payApi().queryAvailablePayModel(payChannelSelectDTO.getCanteenId());
         AllocPayModel merchantPayModel = this.allocMetadataApi.payApi().queryAvailablePayModel((Long)null);
         List<Integer> activePayChannels = this.activePayChannels(canteenPayModel, merchantPayModel);
         resultVO = this.initSearchResult(payChannelSelectDTO);
         Iterator var7 = activePayChannels.iterator();

         while(var7.hasNext()) {
            Integer channel = (Integer)var7.next();
            PayService payService = this.beanOfChannel(channel);
            boolean ifContinue = true;

            try {
               ifContinue = payService.payChannelSelect(selectType, payChannelSelectDTO, canteenPayModel, merchantPayModel, this.payChannelSelectService, resultVO);
            } catch (Exception var12) {
               resultVO.setErrorInfo(var12);
            }

            LogUtil.info("[支付渠道判断]单渠道判断结果", channel, ifContinue, resultVO.getPayChannelSplits(), resultVO.getErrorMsg());
            if (!ifContinue) {
               break;
            }
         }

         this.payCustomBusiness.didPayChannelSelectV2(selectType, payChannelSelectDTO, resultVO);
         LogUtil.info("[支付渠道判断]结果", resultVO);
         if (resultVO.hasErrorInfo()) {
            throw new ServiceException("暂不支持此支付方式");
         } else if (resultVO.getPayChannel() == null) {
            throw new ServiceException("不支持当前支付方式");
         } else {
            return resultVO;
         }
      }
   }

   protected PayChannelSelectResultVO initSearchResult(PayChannelSelectDTO payChannelSelectDTO) {
      PayChannelSelectResultVO resultVO = PayChannelSelectResultVO.of(payChannelSelectDTO);
      if (NuclearModeEnum.isQrCode(payChannelSelectDTO.getNuClearMode()) && LeCodeUtil.isLeCode(payChannelSelectDTO.getAuthCode())) {
         try {
            OrdLeCodeDTO ordLeCodeDTO = LeCodeUtil.readLeCode(payChannelSelectDTO.getAuthCode());
            if (ordLeCodeDTO.ifPersonalPay()) {
               payChannelSelectDTO.setCustId(LeCodeUtil.getPlatformId(ordLeCodeDTO));
            } else if (ordLeCodeDTO.ifCoupon()) {
               Long couponId = LeCodeUtil.getPlatformId(ordLeCodeDTO);
               payChannelSelectDTO.setCouponNum(couponId.toString());
               resultVO.setCouponId(couponId.toString());
            }
         } catch (Exception var5) {
            resultVO.setErrorInfo(var5);
         }
      }

      this.fillCustPayVO(payChannelSelectDTO, resultVO, true);
      return resultVO;
   }

   protected List<Integer> activePayChannels(AllocPayModel canteenPayModel, AllocPayModel merchantPayModel) {
      List<Integer> activePayChannels = CollUtil.newArrayList(new Integer[0]);
//      activePayChannels.add(PayChannelEnum.COUPON.getKey());
      activePayChannels.add(PayChannelEnum.ACC.getKey());
//      activePayChannels.add(PayChannelEnum.OTHER.getKey());
      if (canteenPayModel.supportPayChannel(PayChannelEnum.ALI.getKey())) {
         activePayChannels.add(PayChannelEnum.ALI.getKey());
      }

      if (canteenPayModel.supportPayChannel(PayChannelEnum.WECHAT.getKey())) {
         activePayChannels.add(PayChannelEnum.WECHAT.getKey());
      }

      CollUtil.addAllIfNotContains(activePayChannels, canteenPayModel.supportPayChannels());
      if (merchantPayModel.supportPayChannel(PayChannelEnum.THIRD.getKey())) {
         activePayChannels.remove(PayChannelEnum.THIRD.getKey());
         activePayChannels.add(PayChannelEnum.THIRD.getKey());
      }

      return activePayChannels;
   }

   public PayService beanOfChannel(Integer payChannel) {
      PayService payService = this.payCustomBusiness.beanOfChannel(payChannel);
      if (payService != null) {
         return payService;
      } else {
         Optional<Class<?>> payServiceType = PayChannelEnum.getBeanClass(payChannel);
         if (payServiceType.isPresent()) {
            return (PayService)this.beanFactory.getBean((Class)payServiceType.get());
         } else {
            log.info("===不支持的支付方式 {}", payChannel);
            throw new ServiceException("不支持当前支付方式");
         }
      }
   }

   public void fillCustPayVO(PayChannelSelectDTO payChannelSelectDTO, PayChannelSelectResultVO resultVO, boolean saveErrorIfNotExist) {
      try {
         boolean useOpenidSearch = !LeNumUtil.isValidId(payChannelSelectDTO.getCustId()) && CharSequenceUtil.isNotBlank(payChannelSelectDTO.getOpenId());
         boolean useSerialNumSearch = NuclearModeEnum.isCard(payChannelSelectDTO.getNuClearMode()) && CharSequenceUtil.isNotBlank(payChannelSelectDTO.getSerialNum());
         CustPayDTO custPayDTO = (new CustPayDTO()).setCustId(useSerialNumSearch ? null : payChannelSelectDTO.getCustId()).setOpenid(useOpenidSearch ? payChannelSelectDTO.getOpenId() : null).setSerialNum(useSerialNumSearch ? payChannelSelectDTO.getSerialNum() : null);
         if (!LeNumUtil.isValidId(custPayDTO.getCustId()) && CharSequenceUtil.isBlank(custPayDTO.getOpenid()) && CharSequenceUtil.isBlank(custPayDTO.getSerialNum())) {
            log.warn("支付渠道判断，人员查询条件为空，支付渠道判断跳过人员查询");
            return;
         }

         CustPayVO custPayVO = this.custInfoApi.getCustPayVO(custPayDTO);
         if (useSerialNumSearch) {
            if (CardStatusEnum.LOSS.getKey().equals(custPayVO.getCardStatus())) {
               throw new ServiceException("卡片已挂失");
            }

            if (ObjectUtil.isNotNull(custPayVO.getValidityDate()) && custPayVO.getValidityDate().isBefore(LocalDate.now())) {
               throw new ServiceException("卡片使用期限已过期");
            }
         }

         resultVO.setCustPayVO(custPayVO);
      } catch (Exception var8) {
         log.warn("查询查到卡关联人员报错", var8);
         Integer errorCode =  LeRetCodeEnum.FAIL.getKey();
         if (!LeRetCodeEnum.CUST_PERSONAL_NO_EXIT.getKey().equals(errorCode) && saveErrorIfNotExist) {
            resultVO.setErrorInfo(var8);
         }
      }

   }
}
