package com.bonus.core.account.v3.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.core.account.v3.api.dto.AccOrdBaseDTO;
import com.bonus.core.account.v3.api.dto.AccOrdRefundDTO;
import com.bonus.core.account.v3.constants.AccOrdMixPayDealStateEnum;
import com.bonus.core.account.v3.constants.AccTradeStateEnum;
import com.bonus.core.account.v3.constants.AccTradeTypeEnum;
import com.bonus.core.account.v3.constants.AccUpdateWalletOperateEnum;
import com.bonus.core.account.v3.custom.AccPayUniqueCustomBusiness;
import com.bonus.core.account.v3.metadata.enums.AccWalletIdEnum;
import com.bonus.core.account.v3.metadata.model.AccMetadataModel;
import com.bonus.core.account.v3.metadata.service.AccMetadataService;
import com.bonus.core.account.v3.model.AccPayFrozenDetail;
import com.bonus.core.account.v3.model.AccTradeWalletDetail;
import com.bonus.core.account.v3.mq.send.AccSendMq;
import com.bonus.core.account.v3.po.*;
import com.bonus.core.account.v3.service.*;
import com.bonus.core.account.v3.utils.AccUtils;
import com.bonus.core.account.v3.web.dto.AccOrdMixPayResultDTO;
import com.bonus.core.account.v3.web.vo.*;
import com.bonus.core.marketing.v2.api.MarketApi;
import com.bonus.core.marketing.v2.rule.pay.dto.RulePayComputeDTO;
import com.bonus.core.marketing.v2.rule.pay.dto.RulePayResultDTO;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceResultDTO;
import com.bonus.core.pay.common.constants.PayChannelEnum;
import com.bonus.core.pay.common.constants.PayStateEnum;
import com.bonus.core.pay.common.constants.PayTypeEnum;
import com.bonus.i18n.I18n;
import com.bonus.utils.id.Id;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class AccPayServiceImpl implements AccPayService {
   private static final Logger log = LoggerFactory.getLogger(AccPayServiceImpl.class);
   @Resource
   @Lazy
   private AccInfoService accInfoService;
   @Resource
   @Lazy
   private MarketApi marketApi;
   @Resource
   @Lazy
   private AccMetadataService accMetadataService;
   @Resource
   @Lazy
   private AccTradeService accTradeService;
   @Resource
   @Lazy
   private AccWalletInfoService accWalletInfoService;
   @Resource
   @Lazy
   private AccInfoHandleBusiness accInfoHandleBusiness;
   @Resource
   @Lazy
   private AccPayUniqueCustomBusiness accPayUniqueCustomBusiness;
   @Resource
   @Lazy
   private AccBusinessService accBusinessService;
   @Resource
   @Lazy
   private AccTradeWalletDetailService accTradeWalletDetailService;

   @Autowired
   @Lazy
   private AccPayFrozenDetailService accPayFrozenDetailService;

   @Override
   @Transactional(
      rollbackFor = {Exception.class},
      propagation = Propagation.REQUIRES_NEW
   )
   public AccOrdBasicsVO accPayForOffline(AccOrdBaseDTO accOrdOfflineDTO) {
      log.info("[离线订单支付]入参_{}", JSON.toJSONString(accOrdOfflineDTO));
      AccUtils.checkAccPayUpgradeTask(accOrdOfflineDTO.getCustId());

      AccOrdBasicsVO var3;
      try {
         AccOrdBasicsVO accOrdBasicsVO = this.accPayUniqueCustomBusiness.prepAccPayForOffline(accOrdOfflineDTO);
         if (!ObjectUtil.isNotNull(accOrdBasicsVO)) {
            AccInfoVO accInfoVO = this.getAccInfoByCustId(accOrdOfflineDTO.getCustId());
            List<Integer> walletIdList = this.getWalletPayIdList(accOrdOfflineDTO);
            log.info("[离线订单支付]获取钱包扣款顺序:{}", JSONUtil.toJsonStr(walletIdList));
            AccPayPO accPayPO = this.accInfoHandleBusiness.amountCalculationByRulePrice(accInfoVO, walletIdList, accOrdOfflineDTO.getRulePriceResult());
            log.info("[离线订单支付]计算金额明细：{}", JSON.toJSONString(accPayPO));
            this.accPayUniqueCustomBusiness.didOfflinePayCalculation(accPayPO, accOrdOfflineDTO);
            List<AccWalletPayPO> walletPayPOList = accPayPO.getWalletPayList();
            if (ObjectUtil.isNotNull(accPayPO.getUnpaidBalance()) && accPayPO.getUnpaidBalance().compareTo(BigDecimal.ZERO) > 0) {
               this.addUnpaidBalanceAccPay(accInfoVO, walletPayPOList, accPayPO.getUnpaidBalance());
            }

            BigDecimal realAmount = (BigDecimal)walletPayPOList.stream().map(AccWalletPayPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            AccConsumeWalletVO accConsumeWalletVO = this.accBusinessService.doConsumeUpdateWalletAndAddTradeV2((new AccConsumeUpdateWalletPO()).setCustId(accInfoVO.getCustId()).setPsnType(accInfoVO.getPsnType()).setOrgId(accInfoVO.getOrgId()).setTradeType(AccTradeTypeEnum.CONSUME.getKey()).setAmount(realAmount).setMachineSn(accOrdOfflineDTO.getMchSn()).setRemark(accOrdOfflineDTO.getRemark()).setOrderTradeId(accOrdOfflineDTO.getOrderId()).setWalletPayList(walletPayPOList).setPayWalletIdList(walletIdList));
            AccOrdBasicsVO var9 = this.assembledAccOrdTradeDetailV2(accConsumeWalletVO, walletPayPOList);
            return var9;
         }

         var3 = accOrdBasicsVO;
      }  catch (Exception var15) {
         log.info("[离线订单支付]系统错误：{}", var15.getMessage(), var15);
         throw new ServiceException("[离线订单支付]系统错误");
      } finally {
         AccUtils.accPayUnLockByCustId(accOrdOfflineDTO.getCustId());
      }

      return var3;
   }


   @Override
   @Transactional(
      rollbackFor = {Exception.class},
      propagation = Propagation.REQUIRES_NEW
   )
   public AccOrdBasicsVO accOrdForRefund(AccOrdRefundDTO accOrdRefundDTO) {
      log.info("[退款订单]入参_{}", JSON.toJSONString(accOrdRefundDTO));
      AccUtils.checkAccPayUpgradeTask(accOrdRefundDTO.getCustId());

      AccOrdBasicsVO var12;
      try {
         if (accOrdRefundDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            AccOrdBasicsVO var20 = new AccOrdBasicsVO();
            return var20;
         }

         AccInfoVO accInfoVO = this.getAccInfoByCustId(accOrdRefundDTO.getCustId());
         List<AccTradeWalletDetail> payTradeList = this.accTradeWalletDetailService.queryAccTradeWalletDetailByLeOrdNo(accOrdRefundDTO.getOrderId(), Arrays.asList(AccTradeTypeEnum.CONSUME.getKey(), AccTradeTypeEnum.CONSUME_REPAIR.getKey()));
         log.info("[退款订单]根据订单id查询账户消费数据,orderId={}，size={}", accOrdRefundDTO.getOrderId(), payTradeList.size());
         if (ObjectUtil.isEmpty(payTradeList)) {
            throw new ServiceException("acc_ord_not_exits_record");
         }

         BigDecimal orderAmount = (BigDecimal)payTradeList.stream().map(AccTradeWalletDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
         Long originTradeId = ((AccTradeWalletDetail)payTradeList.get(0)).getTradeId();
         List<AccTradeWalletDetail> refundTradeList = this.accTradeWalletDetailService.queryAccTradeWalletDetailByOriginTradeId(originTradeId, AccTradeTypeEnum.CONSUME_REFUND.getKey());
         BigDecimal refundedAmount = BigDecimal.ZERO;
         Map<Integer, BigDecimal> refundedMap = Maps.newHashMap();
         if (ObjectUtil.isNotEmpty(refundTradeList)) {
            refundedAmount = (BigDecimal)refundTradeList.stream().map(AccTradeWalletDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            refundedMap = (Map)refundTradeList.stream().collect(Collectors.groupingBy(AccTradeWalletDetail::getWalletId, Collectors.reducing(BigDecimal.ZERO, AccTradeWalletDetail::getAmount, BigDecimal::add)));
            log.info("[退款订单]根据订单id查询已退款金额,orderId={}，refundedAmount={}", originTradeId, refundedAmount);
         }

         if (orderAmount.compareTo(refundedAmount.add(accOrdRefundDTO.getAmount())) < 0) {
            throw new ServiceException("acc_refund_amount_exception");
         }

         List<AccWalletPayPO> walletRefundPayList = Lists.newArrayList();
         long tradeId = this.accOrdForRefundHandle(accInfoVO, payTradeList, (Map)refundedMap, accOrdRefundDTO, originTradeId, walletRefundPayList);
         var12 = this.assembledAccOrdTradeDetail(accInfoVO.getCustId(), tradeId, walletRefundPayList);
      } catch (Exception var18) {
         log.info("[退款订单]系统错误：{}", var18.getMessage(), var18);
         throw new ServiceException("[退款订单]系统错误");
      } finally {
         AccUtils.accPayUnLockByCustId(accOrdRefundDTO.getCustId());
      }

      return var12;
   }

   protected Long accOrdForRefundHandle(AccInfoVO accInfoVO, List<AccTradeWalletDetail> payTradeList, Map<Integer, BigDecimal> refundedMap, AccOrdRefundDTO accOrdRefundDTO, Long originTradeId, List<AccWalletPayPO> walletRefundPayList) {
      long tradeId = Id.next();
      LocalDateTime now = LocalDateTime.now();
      Integer tradeType = AccTradeTypeEnum.CONSUME_REFUND.getKey();
      BigDecimal remainingAmount = accOrdRefundDTO.getAmount();
      Iterator var12 = payTradeList.iterator();

      while(var12.hasNext()) {
         AccTradeWalletDetail payTrade = (AccTradeWalletDetail)var12.next();
         Integer walletId = payTrade.getWalletId();
         BigDecimal walletRefundedAmount = ObjectUtil.isNotNull(refundedMap.get(walletId)) ? (BigDecimal)refundedMap.get(walletId) : BigDecimal.ZERO;
         BigDecimal walletCanUseAmount = payTrade.getAmount().subtract(walletRefundedAmount);
         if (walletCanUseAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal walletAmount;
            if (walletCanUseAmount.compareTo(remainingAmount) <= 0) {
               walletAmount = walletCanUseAmount;
               remainingAmount = remainingAmount.subtract(walletCanUseAmount);
            } else {
               walletAmount = remainingAmount;
               remainingAmount = BigDecimal.ZERO;
            }

            AccWalletBalanceUpdatePO rechargePo = (new AccWalletBalanceUpdatePO()).setOperationType(AccUpdateWalletOperateEnum.AUGMENT_BAL).setCustId(accInfoVO.getCustId()).setWalletId(walletId).setAmount(walletAmount);
            AccUpdateWalletBalanceVO accUpdateWalletBalanceVO = this.accWalletInfoService.updateAccWalletBalance(rechargePo);
            AccTradeWalletPO accTradeWalletPo = AccTradeWalletPO.builder().tradeId(tradeId).custId(accInfoVO.getCustId()).walletId(walletId).tradeType(tradeType).amount(walletAmount).walletBal(AccUtils.getWalletBal(accUpdateWalletBalanceVO.getWalletInfoList(), walletId)).frozenBalance(AccUtils.getWalletFrozenBal(accUpdateWalletBalanceVO.getWalletInfoList(), walletId)).tradeTime(now).build();
            this.accTradeWalletDetailService.insertAccTradeWalletDetail(accTradeWalletPo);
            walletRefundPayList.add(AccWalletPayPO.builder().walletId(walletId).custId(accInfoVO.getCustId()).amount(walletAmount).walletBal(AccUtils.getWalletBal(accUpdateWalletBalanceVO.getWalletInfoList(), walletId)).build());
            if (remainingAmount.compareTo(BigDecimal.ZERO) == 0) {
               break;
            }
         }
      }

      AccUpdateWalletBalanceVO accWalletBalance = this.accWalletInfoService.getAccWalletBalanceByCustId(accInfoVO.getCustId());
      AccTradeAddPO accTradeAddPo = AccTradeAddPO.builder().tradeId(tradeId).tradeType(tradeType).tradeTime(now).custId(accInfoVO.getCustId()).psnType(accInfoVO.getPsnType()).orgId(accInfoVO.getOrgId()).actualAmount(accOrdRefundDTO.getAmount()).amount(accOrdRefundDTO.getAmount()).walletBalTotal(accWalletBalance.getAccBalTotal()).accAllBal(accWalletBalance.getAccAllBal()).payChannel(PayChannelEnum.ACC.getKey()).payType(PayTypeEnum.MEAL_CARD.getKey()).payState(PayStateEnum.PAY_SUCC.getKey()).tradeState(AccTradeStateEnum.TAKE_EFFECT.getKey()).leOrdNo(accOrdRefundDTO.getRefundOrderId()).originTradeId(originTradeId).crby(AccUtils.getOperatorName()).build();
      this.accTradeService.insertAccTradeForTradeId(accTradeAddPo);
      log.info("[退款订单]->修改钱包,新增记录结束");
      return tradeId;
   }

   protected AccInfoVO getAccInfoByCustId(Long custId) {
      AccInfoVO accInfoVO = this.accInfoService.getAccInfoVoByCustId(custId);
      this.accInfoService.checkAccInfoAndStatus(accInfoVO);
      return accInfoVO;
   }

   protected List<Integer> getWalletPayIdList(AccOrdBaseDTO accOrdOnlineDTO) {
      RulePayComputeDTO rulePayComputeDTO = new RulePayComputeDTO(accOrdOnlineDTO);
      RulePayResultDTO rulePayResultDTO = this.marketApi.rulePayCompute(rulePayComputeDTO);
      return CollUtil.isNotEmpty(rulePayResultDTO.getWalletIds()) ? rulePayResultDTO.getWalletIds() : this.getWalletPayDefaultOrder();
   }

   public List<Integer> getWalletPayDefaultOrder() {
      List<Integer> list = new ArrayList();
      AccMetadataModel accMetadataModel = this.accMetadataService.queryMetadata();
      String accPayOrder;
      if (ObjectUtil.isAllNotEmpty(new Object[]{accMetadataModel, accMetadataModel.getAccPayOrder()})) {
         accPayOrder = accMetadataModel.getAccPayOrder();
         log.info("获取配置项扣款优先级:{}", JSONUtil.toJsonStr(accPayOrder));
      } else {
         accPayOrder = AccWalletIdEnum.getAllWalletId();
         log.info("获取默认扣款优先级:{}", JSONUtil.toJsonStr(accPayOrder));
      }

      String[] walletIds = accPayOrder.split(",");
      String[] var5 = walletIds;
      int var6 = walletIds.length;

      for(int var7 = 0; var7 < var6; ++var7) {
         String walletId = var5[var7];
         list.add(Integer.valueOf(walletId));
      }

      return list;
   }

   protected void addUnpaidBalanceAccPay(AccInfoVO accInfoVO, List<AccWalletPayPO> walletPayList, BigDecimal unpaidBalance) {
      Map<Integer, AccWalletPayPO> walletPayMap = (Map)walletPayList.stream().collect(Collectors.toMap(AccWalletPayPO::getWalletId, Function.identity()));
      AccMetadataModel accMetadataModel = this.accMetadataService.queryMetadata();
      log.info("获取账户配置项：{}", JSONUtil.toJsonStr(accMetadataModel));
      Integer walletId = AccWalletIdEnum.WALLET.getKey();
      if (ObjectUtil.isNotNull(accMetadataModel) && CharSequenceUtil.isNotBlank(accMetadataModel.getOfflineWalletPay())) {
         AccWalletIdEnum walletIdEnum = AccWalletIdEnum.getEnum(Integer.valueOf(accMetadataModel.getOfflineWalletPay()));
         if (ObjectUtil.isNotNull(walletIdEnum)) {
            walletId = walletIdEnum.getKey();
         }
      }

      AccWalletPayPO walletPay = (AccWalletPayPO)walletPayMap.get(walletId);
      if (ObjectUtil.isNotNull(walletPay)) {
         walletPay.setWalletBal(walletPay.getWalletBal().subtract(unpaidBalance));
         walletPay.setAmount(walletPay.getAmount().add(unpaidBalance));
      } else {
         walletPay = new AccWalletPayPO();
         walletPay.setWalletId(walletId);
         BigDecimal walletBal = AccUtils.getWalletBal(accInfoVO.getWalletInfoList(), walletId);
         walletPay.setWalletBal(walletBal.subtract(unpaidBalance));
         walletPay.setAmount(unpaidBalance);
         walletPayList.add(walletPay);
      }

   }

   protected AccOrdBasicsVO assembledAccOrdTradeDetail(Long custId, Long accTradeId, List<AccWalletPayPO> payWalletlist) {
      AccInfoVO newAccInfoVO = this.accInfoService.getAccInfoVoByCustId(custId);
      log.info("账户支付完成,重新获取账户信息:{}", JSONUtil.toJsonStr(newAccInfoVO));
      return AccUtils.transformAccOrdTradeDetailV2(newAccInfoVO, accTradeId, payWalletlist);
   }

   protected AccOrdBasicsVO assembledTrialCalculation(Long custId, List<AccWalletPayPO> payWalletlist) {
      AccInfoVO newAccInfoVO = this.accInfoService.getAccInfoVoByCustId(custId);
      log.info("账户试算支付完成,重新获取账户信息:{}", JSONUtil.toJsonStr(newAccInfoVO));
      return AccUtils.transformAccOrdTradeDetailV4(newAccInfoVO, payWalletlist);
   }

   protected AccOrdBasicsVO assembledAccOrdTradeDetailV2(AccConsumeWalletVO accConsumeWalletVO, List<AccWalletPayPO> payWalletList) {
      return AccUtils.transformAccOrdTradeDetailV3(accConsumeWalletVO.getAccTradeId(), accConsumeWalletVO.getWalletInfoList(), payWalletList);
   }

   @Transactional(
           rollbackFor = {Exception.class},
           propagation = Propagation.REQUIRES_NEW
   )
   public AccOrdBasicsVO accPayForMixPay(AccOrdBaseDTO accPayMixPayDTO) {
      log.info("[订单混合支付]入参_{}", JSON.toJSONString(accPayMixPayDTO));
      AccUtils.checkAccPayUpgradeTask(accPayMixPayDTO.getCustId());

      AccOrdBasicsVO var3;
      try {
         AccOrdBasicsVO accOrdBasicsTemp = this.accPayUniqueCustomBusiness.prepAccPayForMixPay(accPayMixPayDTO);
         if (!ObjectUtil.isNotNull(accOrdBasicsTemp)) {
            AccInfoVO accInfoVO = this.getAccInfoByCustId(accPayMixPayDTO.getCustId());
            List<Integer> walletIdList = this.getWalletPayIdList(accPayMixPayDTO);
            log.info("[订单混合支付]获取钱包扣款顺序:{}", JSONUtil.toJsonStr(walletIdList));
            AccPayPO accPayPO = this.accInfoHandleBusiness.amountCalculationByRulePrice(accInfoVO, walletIdList, accPayMixPayDTO.getRulePriceResult());
            log.info("[订单混合支付]计算金额明细：{}", JSON.toJSONString(accPayPO));
            this.accPayUniqueCustomBusiness.didMixPayCalculation(accPayPO, accPayMixPayDTO);
            List<AccWalletPayPO> walletPayList = accPayPO.getWalletPayList();
            if (CollUtil.isNotEmpty(walletPayList)) {
               Iterator var7 = walletPayList.iterator();

               while(var7.hasNext()) {
                  AccWalletPayPO walletPay = (AccWalletPayPO)var7.next();
                  AccPayFrozenDetailPO payFrozenDetail = AccPayFrozenDetailPO.builder().ordId(accPayMixPayDTO.getOrderId()).amount(walletPay.getAmount()).walletId(walletPay.getWalletId()).custId(walletPay.getCustId()).build();
                  this.accPayFrozenDetailService.insertAccPayFrozenDetail(payFrozenDetail);
                  this.accWalletInfoService.updateAccWalletInfoForUse(walletPay.getCustId(), walletPay.getWalletId(), walletPay.getAmount());
               }
            }

            AccOrdBasicsVO accOrdBasicsVO = this.assembledAccOrdTradeDetail(accInfoVO.getCustId(), (Long)null, walletPayList);
            accOrdBasicsVO.setUnpaidBalance(accPayPO.getUnpaidBalance());
            AccOrdBasicsVO var19 = accOrdBasicsVO;
            return var19;
         }

         var3 = accOrdBasicsTemp;
      } catch (ServiceException var14) {
         throw new ServiceException(var14.getMessage(), var14.getCode());
      } catch (Exception var15) {
         log.info("[订单混合支付]系统错误：{}", var15.getMessage(), var15);
         throw new ServiceException(var15.getMessage());
      } finally {
         AccUtils.accPayUnLockByCustId(accPayMixPayDTO.getCustId());
      }

      return var3;
   }

   @Transactional(
           rollbackFor = {Exception.class},
           propagation = Propagation.REQUIRES_NEW
   )
   public AccOrdBasicsVO accPayForOnline(AccOrdBaseDTO accOrdOnlineDTO) {
      log.info("[在线订单支付]入参_{}", JSON.toJSONString(accOrdOnlineDTO));
      AccUtils.checkAccPayUpgradeTask(accOrdOnlineDTO.getCustId());

      AccOrdBasicsVO var3;
      try {
         AccOrdBasicsVO accOrdBasicsVO = this.accPayUniqueCustomBusiness.prepAccPayForOnline(accOrdOnlineDTO);
         if (!ObjectUtil.isNotNull(accOrdBasicsVO)) {
            AccInfoVO accInfoVO = this.getAccInfoByCustId(accOrdOnlineDTO.getCustId());
            List<Integer> walletIdList = this.getWalletPayIdList(accOrdOnlineDTO);
            log.info("[在线订单支付]获取钱包扣款顺序:{}", JSONUtil.toJsonStr(walletIdList));
            AccPayPO accPayPo = this.accInfoHandleBusiness.amountCalculationByRulePrice(accInfoVO, walletIdList, accOrdOnlineDTO.getRulePriceResult());
            log.info("[在线订单支付]计算金额明细：{}", JSON.toJSONString(accPayPo));
            this.accPayUniqueCustomBusiness.didOnlinePayCalculation(accPayPo, accOrdOnlineDTO);
            if (ObjectUtil.isNotNull(accPayPo.getUnpaidBalance()) && accPayPo.getUnpaidBalance().compareTo(BigDecimal.ZERO) > 0) {
               log.info("[在线订单支付]账户余额不足");
               AccOrdBasicsVO var18 = AccUtils.transformAccOrdNotEnoughAmount(accInfoVO, accPayPo.getUnpaidBalance());
               return var18;
            }

            List<AccWalletPayPO> walletPayPoList = accPayPo.getWalletPayList();
            if (!Boolean.TRUE.equals(accOrdOnlineDTO.getIfTrialCalculation())) {
               BigDecimal realAmount = (BigDecimal)walletPayPoList.stream().map(AccWalletPayPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
               AccConsumeWalletVO accConsumeWalletVO = this.accBusinessService.doConsumeUpdateWalletAndAddTradeV2((new AccConsumeUpdateWalletPO()).setCustId(accInfoVO.getCustId()).setPsnType(accInfoVO.getPsnType()).setOrgId(accInfoVO.getOrgId()).setTradeType(AccTradeTypeEnum.CONSUME.getKey()).setAmount(realAmount).setMachineSn(accOrdOnlineDTO.getMchSn()).setRemark(accOrdOnlineDTO.getRemark()).setOrderTradeId(accOrdOnlineDTO.getOrderId()).setWalletPayList(walletPayPoList).setPayWalletIdList(walletIdList));
               AccOrdBasicsVO var9 = this.assembledAccOrdTradeDetailV2(accConsumeWalletVO, walletPayPoList);
               return var9;
            }

            AccOrdBasicsVO var7 = this.assembledTrialCalculation(accInfoVO.getCustId(), walletPayPoList);
            return var7;
         }

         var3 = accOrdBasicsVO;
      } catch (ServiceException var14) {
         throw new ServiceException(var14.getMessage(), var14.getCode());
      } catch (Exception var15) {
         log.info("[在线订单支付]系统错误：{}", var15.getMessage(), var15);
         throw new ServiceException(var15.getMessage());
      } finally {
         AccUtils.accPayUnLockByCustId(accOrdOnlineDTO.getCustId());
      }

      return var3;
   }

   @Transactional(
           rollbackFor = {Exception.class},
           propagation = Propagation.REQUIRES_NEW
   )
   public AccOrdBasicsVO accPayForMixPayResult(AccOrdMixPayResultDTO accPayMixPayResultDTO) {
      log.info("[订单混合支付回调]入参_{}", JSON.toJSONString(accPayMixPayResultDTO));
      AccUtils.checkAccPayUpgradeTask(accPayMixPayResultDTO.getCustId());

      AccOrdBasicsVO var6;
      try {
         AccInfoVO accInfoVO = this.getAccInfoByCustId(accPayMixPayResultDTO.getCustId());
         AccOrdMixPayDealStateEnum stateEnum = AccOrdMixPayDealStateEnum.getEnum(accPayMixPayResultDTO.getDealState());
         if (ObjectUtil.isNull(stateEnum)) {
            throw new ServiceException(I18n.getMessage("acc_ord_pay_error_state", new Object[0]));
         }

         List<AccPayFrozenDetail> frozenDetailList = this.accPayFrozenDetailService.queryAccPayFrozenDetailByOrderId(accPayMixPayResultDTO.getOrderId());
         log.info("[订单混合支付回调]冻结明细记录:{}", JSONUtil.toJsonStr(frozenDetailList));
         AccOrdBasicsVO var10000;
         switch (stateEnum) {
            case SUCCESS:
               var10000 = this.getSuccessAccOrdMixVO(accInfoVO, frozenDetailList, accPayMixPayResultDTO);
               break;
            case FAIL_ONLINE:
               var10000 = this.getFailOnlineAccOrdMixVO(accInfoVO, frozenDetailList);
               break;
            case FAIL_OFFLINE:
               var10000 = this.getFailOfflineAccOrdMixVO(accInfoVO, frozenDetailList, accPayMixPayResultDTO);
               break;
            default:
               throw new ServiceException(I18n.getMessage("acc_ord_pay_error_state", new Object[0]));
         }

         AccOrdBasicsVO mixVO = var10000;
         this.accPayFrozenDetailService.deleteFrozenDetailByOrderId(accPayMixPayResultDTO.getOrderId());
         var6 = mixVO;
      } catch (ServiceException var11) {
         throw new ServiceException(var11.getMessage(), var11.getCode());
      } catch (Exception var12) {
         log.info("[订单混合支付回调]系统错误：{}", var12.getMessage(), var12);
         throw new ServiceException(var12.getMessage());
      } finally {
         AccUtils.accPayUnLockByCustId(accPayMixPayResultDTO.getCustId());
      }

      return var6;
   }

   protected AccOrdBasicsVO getSuccessAccOrdMixVO(AccInfoVO accInfoVO, List<AccPayFrozenDetail> frozenDetailList, AccOrdMixPayResultDTO accPayMixPayResultDTO) {
      if (ObjectUtil.isEmpty(frozenDetailList)) {
         AccOrdBasicsVO accOrdMixVO = AccUtils.transformAccOrdTradeDetailV2(accInfoVO, (Long)null, (List)null);
         accOrdMixVO.setUnpaidBalance(BigDecimal.ZERO);
         return accOrdMixVO;
      } else {
         List<AccWalletPayPO> walletPayList = this.transformAccWalletPayPOList(accInfoVO, frozenDetailList);
         BigDecimal realAmount = (BigDecimal)walletPayList.stream().map(AccWalletPayPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
         Long tradeId = this.accTradeService.insertAccTradeAndDetail(accInfoVO, AccTradeTypeEnum.CONSUME.getKey(), realAmount, (String)null, walletPayList, accPayMixPayResultDTO.getOrderId(), (String)null, PayStateEnum.PART_PAY.getKey(), false);
         AccOrdBasicsVO mixVO = this.assembledAccOrdTradeDetail(accInfoVO.getCustId(), tradeId, walletPayList);
         mixVO.setUnpaidBalance(BigDecimal.ZERO);
         return mixVO;
      }
   }

   protected List<AccWalletPayPO> transformAccWalletPayPOList(AccInfoVO accInfoVO, List<AccPayFrozenDetail> frozenDetailList) {
      List<AccWalletPayPO> accWalletPayList = Lists.newArrayList();
      Map<Integer, AccWalletInfoVO> walletInfoMap = (Map)accInfoVO.getWalletInfoList().stream().collect(Collectors
              .toMap(AccWalletInfoVO::getWalletId, Function.identity()));
      frozenDetailList.forEach((frozenDetail) -> {
         AccWalletPayPO accWalletPay = new AccWalletPayPO();
         AccWalletInfoVO accWalletInfo = (AccWalletInfoVO)walletInfoMap.get(frozenDetail.getWalletId());
         accWalletPay.setWalletId(frozenDetail.getWalletId());
         accWalletPay.setAmount(frozenDetail.getAmount());
         accWalletPay.setWalletBal(accWalletInfo.getWalletBal());
         accWalletPay.setCustId(accInfoVO.getCustId());
         accWalletPayList.add(accWalletPay);
      });
      return accWalletPayList;
   }

   protected AccOrdBasicsVO getFailOnlineAccOrdMixVO(AccInfoVO accInfoVO, List<AccPayFrozenDetail> frozenDetailList) {
      AccOrdBasicsVO accOrdMixVO = AccUtils.transformAccOrdTradeDetailV2(accInfoVO, (Long)null, (List)null);
      accOrdMixVO.setUnpaidBalance(BigDecimal.ZERO);
      if (ObjectUtil.isEmpty(frozenDetailList)) {
         return accOrdMixVO;
      } else {
         Map<Integer, AccWalletIdEnum> walletIdEnumMap = AccWalletIdEnum.getEnumMap();
         Map<Integer, AccWalletInfoVO> walletInfoMap = (Map)accInfoVO.getWalletInfoList().stream().collect(Collectors.toMap(AccWalletInfoVO::getWalletId, Function.identity()));
         frozenDetailList.forEach((frozenDetail) -> {
            AccWalletInfoRechargePO rechargePO = AccWalletInfoRechargePO.builder().custId(accInfoVO.getCustId()).walletId(frozenDetail.getWalletId()).amount(frozenDetail.getAmount()).build();
            this.accWalletInfoService.updateAccWalletInfoForRecharge(rechargePO);
            AccWalletIdEnum walletIdEnum = (AccWalletIdEnum)walletIdEnumMap.get(frozenDetail.getWalletId());
            AccWalletInfoVO walletInfoVO = (AccWalletInfoVO)walletInfoMap.get(frozenDetail.getWalletId());
            switch (walletIdEnum) {
               case WALLET:
                  accOrdMixVO.setWalletBal(walletInfoVO.getWalletBal().add(frozenDetail.getAmount()));
                  break;
               case SUBSIDY:
                  accOrdMixVO.setSubBal(walletInfoVO.getWalletBal().add(frozenDetail.getAmount()));
                  break;
               case LUCK_MONEY:
                  accOrdMixVO.setRedBal(walletInfoVO.getWalletBal().add(frozenDetail.getAmount()));
                  break;
               default:
                  throw new ServiceException(I18n.getMessage("acc_wallet_error_exception", new Object[0]));
            }

         });
         return accOrdMixVO;
      }
   }

   protected AccOrdBasicsVO getFailOfflineAccOrdMixVO(AccInfoVO accInfoVO, List<AccPayFrozenDetail> frozenDetailList, AccOrdMixPayResultDTO accPayMixPayResultDTO) {
      BigDecimal unpaidBalance = accPayMixPayResultDTO.getUnpaidBalance();
      if (ObjectUtil.isEmpty(frozenDetailList) && BigDecimal.ZERO.compareTo(unpaidBalance) >= 0) {
         AccOrdBasicsVO accOrdMixVO = AccUtils.transformAccOrdTradeDetailV2(accInfoVO, (Long)null, (List)null);
         accOrdMixVO.setUnpaidBalance(unpaidBalance);
         return accOrdMixVO;
      } else {
         List<AccWalletPayPO> walletPayList = this.transformAccWalletPayPOList(accInfoVO, frozenDetailList);
         if (ObjectUtil.isNotNull(unpaidBalance) && unpaidBalance.compareTo(BigDecimal.ZERO) > 0) {
            this.addUnpaidBalanceAccPay(accInfoVO, walletPayList, unpaidBalance);
            accInfoVO.setAccBalTotal(accInfoVO.getAccBalTotal().subtract(unpaidBalance));
            accInfoVO.setAccAllBal(accInfoVO.getAccAllBal().subtract(unpaidBalance));
         }

         log.info("[订单混合支付回调]离线失败,存在未支付金额,继续支付钱包扣款详情:{}", JSONUtil.toJsonStr(walletPayList));
         BigDecimal realAmount = (BigDecimal)walletPayList.stream().map(AccWalletPayPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
         Long tradeId = this.accTradeService.insertAccTradeAndDetail(accInfoVO, AccTradeTypeEnum.CONSUME.getKey(), realAmount, "", walletPayList, accPayMixPayResultDTO.getOrderId(), (String)null, PayStateEnum.PAY_SUCC.getKey(), false);
         if (unpaidBalance.compareTo(BigDecimal.ZERO) > 0) {
            this.accWalletInfoService.updateAccWalletInfoForUse(accInfoVO.getCustId(), AccWalletIdEnum.WALLET.getKey(), unpaidBalance);
         }

         AccOrdBasicsVO mixVO = this.assembledAccOrdTradeDetail(accInfoVO.getCustId(), tradeId, walletPayList);
         mixVO.setUnpaidBalance(BigDecimal.ZERO);
         return mixVO;
      }
   }


}
