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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.core.account.v3.api.AccBusinessApi;
import com.bonus.core.account.v3.constants.AccExceptionRecordStatusEnum;
import com.bonus.core.account.v3.web.dto.AccUpdateExceptionRecordDTO;
import com.bonus.core.common.utils.JacksonUtil;
import com.bonus.core.common.utils.LogUtil;
import com.bonus.core.order.utils.LeNumUtil;
import com.bonus.core.pay.api.dto.UnifyPayDTO;
import com.bonus.core.pay.api.dto.UnifyPaySelectDTO;
import com.bonus.core.pay.api.dto.UnifyRefundDTO;
import com.bonus.core.pay.api.vo.UnifyRefundVO;
import com.bonus.core.pay.common.constants.PayCacheConstants;
import com.bonus.core.pay.common.constants.PayStateEnum;
import com.bonus.core.pay.common.constants.TradeTypeEnum;
import com.bonus.core.pay.common.dto.PayRefundDTO;
import com.bonus.core.pay.common.model.TradeChannel;
import com.bonus.core.pay.common.model.TradeOrderRecharge;
import com.bonus.core.pay.common.model.TradeRecord;
import com.bonus.core.pay.common.service.PayService;
import com.bonus.core.pay.common.service.PayTradeService;
import com.bonus.core.pay.common.service.TradeChannelService;
import com.bonus.core.pay.common.service.TradeRecordService;
import com.bonus.core.pay.common.vo.PayRefundVO;
import com.bonus.core.pay.common.vo.TradeChannelVO;
import com.bonus.core.pay.custom.PayCustomBusiness;
import com.bonus.i18n.I18n;
import com.bonus.utils.id.Id;
import com.fasterxml.jackson.databind.JsonNode;
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.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class RefundBusiness {
   private static final Logger log = LoggerFactory.getLogger(RefundBusiness.class);
   private static final String TRADE_LOCK_LEY = "yst:trade-lock:";
   @Lazy
   @Autowired
   protected TradeRecordService tradeRecordService;
   @Lazy
   @Autowired
   protected TradeChannelService tradeChannelService;
   @Lazy
   @Autowired
   protected ChannelBusiness channelBusiness;
   @Autowired
   @Lazy
   protected PayCustomBusiness payCustomBusiness;
   @Autowired
   @Lazy
   protected PayBusiness payBusiness;
   @Lazy
   @Autowired
   protected AccBusinessApi accBusinessApi;
   @Lazy
   @Autowired
   protected PayTradeService payTradeService;

   @Transactional(
           propagation = Propagation.NOT_SUPPORTED
   )
   public UnifyRefundVO unifyRefund(UnifyRefundDTO refundDTO) {
      LogUtil.info("[统一支付退款]入参", refundDTO);
      UnifyRefundVO payRefundVO = new UnifyRefundVO();

      TradeRecord tradeRecord;
      try {
         this.payCustomBusiness.willPayRefundV2(refundDTO);
         tradeRecord = refundDTO.getTradeId() != null ? this.tradeRecordService.getTradeRecordById(refundDTO.getTradeId())
                 : this.tradeRecordService.getTradeRecordByOrderRechargeId(refundDTO.getOrderRechargeId(), PayStateEnum.PAY_SUCC.getKey(),
                 PayStateEnum.PART_PAY.getKey());
         if (tradeRecord == null) {
            log.error("[统一支付退款]交易记录不存在，{}", refundDTO);
            throw new ServiceException(this.tradeNotExistsMsg());
         }

         if (!PayStateEnum.isPaidState(tradeRecord.getTradeState())) {
            log.error("[统一支付退款]交易记录状态不是已支付，tradeId={},tradeState={}", tradeRecord.getId(), tradeRecord.getTradeState());
            throw new ServiceException(I18n.getMessage("pay.not-paid-state", new Object[0]));
         }

         if (!TradeTypeEnum.isConsumeType(tradeRecord.getTradeType()) && !TradeTypeEnum.isRechargeType(tradeRecord.getTradeType())) {
            log.error("[统一支付退款]交易记录类型不是消费，tradeId={},tradeType={}", tradeRecord.getId(), tradeRecord.getTradeType());
            throw new ServiceException(I18n.getMessage("pay.not-refundable", new Object[0]));
         }
      } catch (Exception var18) {
         log.error("[统一支付退款]初始化异常", var18);
         payRefundVO = UnifyRefundVO.newInstanceOf(refundDTO.getRefundTradeId(), (List)null);
         payRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
         payRefundVO.setMsg(var18 instanceof ServiceException ? var18.getMessage() : PayStateEnum.PAY_FAIL.getDesc());
         return payRefundVO;
      }

      if (!PayCacheConstants.lockTrade(tradeRecord.getId())) {
         log.warn("[统一支付]交易锁定失败");
         payRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
         payRefundVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
         return payRefundVO;
      } else {
         TradeRecord refundTrade;
         try {
            refundDTO.setTradeId(tradeRecord.getId());
            refundTrade = this.packageRefundTradeInfo(refundDTO, tradeRecord);
            refundDTO.setRefundTradeId(refundTrade.getId());
            TradeOrderRecharge tradeOrderRecharge = new TradeOrderRecharge(refundTrade.getId(), refundDTO.getRefundId(), refundDTO.getMacRefundId(), (LocalDateTime)null, (LocalDateTime)null);
            this.tradeRecordService.insertTrade(refundTrade, CollUtil.toList(new TradeOrderRecharge[]{tradeOrderRecharge}));
         } catch (Exception var17) {
            log.warn("[统一支付]交易保存失败", var17);
            payRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            payRefundVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
            PayCacheConstants.unlockTrade(tradeRecord.getId());
            return payRefundVO;
         }

         try {
            if (PayStateEnum.PART_PAY.getKey().equals(tradeRecord.getTradeState())) {
               payRefundVO = UnifyRefundVO.newInstanceOf(refundDTO.getRefundTradeId(), (List)null);
               if (this.accBusinessApi.existExceptionRecordByRelatedId(tradeRecord.getId(), AccExceptionRecordStatusEnum.FAIL.getKey())) {
                  try {
                     AccUpdateExceptionRecordDTO updateExceptionRecordDTO = new AccUpdateExceptionRecordDTO();
                     updateExceptionRecordDTO.setOperatorType(2);
                     updateExceptionRecordDTO.setRelationId(tradeRecord.getId());
                     updateExceptionRecordDTO.setRemark(tradeRecord.getTradeResult());
                     updateExceptionRecordDTO.setRefundAmount(refundTrade.getAmount());
                     this.accBusinessApi.updateAccExceptionRecord(updateExceptionRecordDTO);
                     payRefundVO.setCode(PayStateEnum.PAY_SUCC.getKey());
                     payRefundVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
                     payRefundVO.setRefundAmount(refundTrade.getAmount());
                  } catch (Exception var15) {
                     log.error("[渠道支付退款]调用账户异常处理结果异常", var15);
                     payRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
                     payRefundVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
                  }
               } else {
                  payRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
                  payRefundVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
               }
            } else {
               payRefundVO = this.startRefundFlow(tradeRecord, refundTrade.getId(), refundTrade.getAmount(), refundDTO.getChannelAssignList(), refundDTO.getDetailList(), (List)null);
            }

            LogUtil.info("[统一支付退款]返回结果", payRefundVO);
            this.tradeRecordService.updateTradeRecordState(refundTrade.getId(), payRefundVO);
            log.info("[统一支付退款]更新交易状态完毕");
         } catch (Exception var16) {
            log.error("[统一支付退款]更新记录异常", var16);
            payRefundVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
            payRefundVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
         }

         try {
            if (PayStateEnum.isPayingState(payRefundVO.getCode())) {
               log.info("[统一支付退款]退款中，开始定时查询");
               UnifyPaySelectDTO paySelectDTO = new UnifyPaySelectDTO();
               paySelectDTO.setTradeId(refundTrade.getId());
               paySelectDTO.setSendNoticeMQ(true);
               paySelectDTO.setFromAutoQuery(true);
               this.payTradeService.sendAutoPayResultQuery(paySelectDTO, LocalDateTime.now(), false);
            }

            this.payCustomBusiness.didPayRefundV2(refundDTO, payRefundVO);
         } catch (Exception var13) {
            log.error("[统一支付退款]埋点异常", var13);
         } finally {
            PayCacheConstants.unlockTrade(tradeRecord.getId());
         }

         return payRefundVO;
      }
   }

   public UnifyRefundVO startRefundFlow(TradeRecord tradeRecord, Long refundTradeId,
                                        BigDecimal totalRefundAmount,
                                        List<UnifyRefundDTO.ChannelDetail> channelAssignList,
                                        List<UnifyRefundDTO.Detail> refundDetailList,
                                        List<TradeChannelVO> existsTradeChannels) {
      LogUtil.info("[渠道退款]继续退款", tradeRecord, refundTradeId, totalRefundAmount, channelAssignList, existsTradeChannels);
      UnifyRefundVO globalRefundVO = UnifyRefundVO.newInstanceOf(refundTradeId, existsTradeChannels);

      try {
         boolean isZeroRefund = totalRefundAmount.compareTo(BigDecimal.ZERO) == 0;
         boolean isChannelAssigned = CollUtil.isNotEmpty(channelAssignList);
         BigDecimal leftRefundAmount = totalRefundAmount.subtract(globalRefundVO.getRefundAmount());
         List<TradeChannelVO> tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(tradeRecord.getId());
         Map<Long, UnifyRefundDTO.ChannelDetail> channelDTOMap = CollUtil.isNotEmpty(channelAssignList) ?
                 channelAssignList.stream().collect(Collectors.toMap(UnifyRefundDTO.ChannelDetail::getTradeChannelId, Function.identity()))
                 : MapUtil.empty();
         if (!this.checkRefundAvailable(totalRefundAmount, tradeChannels, channelDTOMap, globalRefundVO)) {
            return globalRefundVO;
         }

         UnifyPayDTO unifyPayDTO = UnifyPayDTO.of(tradeRecord);

         for(int i = tradeChannels.size() - 1; i >= 0; --i) {
            TradeChannelVO tradeChannel = (TradeChannelVO)tradeChannels.get(i);
            BigDecimal detailRefundableAmount = tradeChannel.calcRefundableAmount();
            BigDecimal detailRefundAmount = detailRefundableAmount.compareTo(leftRefundAmount) > 0 ? leftRefundAmount : detailRefundableAmount;
            log.info("[渠道退款]计算渠道退款 渠道总支付:{} 渠道已退:{} 渠道剩余:{} 总剩余应退:{} 本次渠道应退:{}", new Object[]{tradeChannel.getAmount(),
                    tradeChannel.getRefundAmount(), detailRefundableAmount, leftRefundAmount, detailRefundAmount});
            if (!PayStateEnum.isPaySuccessState(tradeChannel.getTradeState())) {
               log.info("[渠道退款]未支付成功的跳过");
            } else if (!isZeroRefund && detailRefundableAmount.compareTo(BigDecimal.ZERO) == 0) {
               log.info("[渠道退款]总退款金额为大于0, 明细可退金额为0，跳过");
            } else {
               UnifyRefundDTO.ChannelDetail channelAssignDTO = (UnifyRefundDTO.ChannelDetail)channelDTOMap.get(tradeChannel.getTradeChannelId());
               if (isChannelAssigned) {
                  if (channelAssignDTO == null) {
                     log.info("[渠道退款]指定渠道不退款，跳过");
                     continue;
                  }

                  detailRefundAmount = channelAssignDTO.getRefundAmount();
               }

               TradeChannelVO existsRefundChannelVO = (TradeChannelVO)globalRefundVO.getRefundDetailList().stream().filter((s) -> {
                  return s.getPayType().equals(tradeChannel.getPayType()) && s.getPayChannel().equals(tradeChannel.getPayChannel());
               }).findFirst().orElse((TradeChannelVO) null);
               TradeChannelVO refundTradeChannel;
               if (existsRefundChannelVO != null) {
                  refundTradeChannel = existsRefundChannelVO;
                  globalRefundVO.fillChannelRefund(existsRefundChannelVO);
               } else {
                  PayRefundDTO dto = PayRefundDTO.of(refundTradeId);
                  dto.setAmount(tradeChannel.getAmount());
                  dto.setRefundAmount(detailRefundAmount);
                  dto.setRefundTradeChannelId(i == tradeChannels.size() - 1 ? refundTradeId : Id.next());
                  if (channelAssignDTO != null && CollUtil.isNotEmpty(channelAssignDTO.getWalletDetailList())) {
                     dto.setWalletDetailList(channelAssignDTO.getWalletDetailList());
                  }

                  dto.setRefundDetailList(refundDetailList);
                  this.fillPayRefundDTO(dto, unifyPayDTO, tradeRecord);
                  refundTradeChannel = this.channelPayRefund(tradeChannel, dto, refundTradeId);
                  globalRefundVO.fillChannelRefund(refundTradeChannel);
                  globalRefundVO.getRefundDetailList().add(refundTradeChannel);
               }

               if (!PayStateEnum.isPaySuccessState(refundTradeChannel.getTradeState())) {
                  break;
               }

               tradeChannel.setRefundAmount(tradeChannel.getRefundAmount().add(detailRefundAmount));
               globalRefundVO.setRefundAmount(globalRefundVO.getRefundAmount().add(detailRefundAmount));
               leftRefundAmount = leftRefundAmount.subtract(detailRefundAmount);
               this.tradeChannelService.updateRefundAmount(tradeChannel.getTradeChannelId(), tradeChannel.getRefundAmount());
               if (leftRefundAmount.compareTo(BigDecimal.ZERO) <= 0) {
                  break;
               }
            }
         }

         if (isZeroRefund && CollUtil.isEmpty(globalRefundVO.getRefundDetailList())) {
            log.info("[渠道退款]0元退款，无渠道明细，直接返回成功");
            globalRefundVO.setCode(PayStateEnum.PAY_SUCC.getKey());
            globalRefundVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
         }

         if (PayStateEnum.isFinishedState(globalRefundVO.getCode()) && PayStateEnum.isFailedState(globalRefundVO.getCode()) && globalRefundVO.getRefundDetailList().stream().anyMatch((s) -> {
            return PayStateEnum.isPaidState(s.getTradeState());
         })) {
            globalRefundVO.setCode(PayStateEnum.PART_PAY.getKey());
            globalRefundVO.setMsg(PayStateEnum.PART_PAY.getDesc());
         }
      } catch (Exception var22) {
         log.error("[渠道退款]退款流程异常", var22);
      }

      return globalRefundVO;
   }

//   public UnifyRefundVO selectAndStartRefundFlow(TradeRecord refundTradeRecord) {
//      List<TradeChannelVO> tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(refundTradeRecord.getId());
//      TradeRecord originalTradeRecord = this.tradeRecordService.getTradeRecordById(refundTradeRecord.getRelatedTradeId());
//      TradeChannelVO lastTradeChannelVO = (TradeChannelVO)CollUtil.getLast(tradeChannels);
//      if (lastTradeChannelVO != null && PayStateEnum.isPayingState(lastTradeChannelVO.getTradeState())) {
//         RefundSelectDTO refundSelectDTO = new RefundSelectDTO();
//         refundSelectDTO.setCanteenId(refundTradeRecord.getCanteenId());
//         RefundSelectVO refundSelectVO = this.channelRefundSelect(lastTradeChannelVO, refundSelectDTO);
//         if (PayStateEnum.isPayingState(refundSelectVO.getCode())) {
//            return UnifyRefundVO.of(refundTradeRecord, tradeChannels);
//         }
//
//         lastTradeChannelVO.setTradeState(refundSelectVO.getCode());
//         lastTradeChannelVO.setTradeResult(refundSelectVO.getMsg());
//      }
//
//      tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(refundTradeRecord.getId());
//      UnifyRefundDTO payRefundDTO = UnifyRefundDTO.ofNullable(refundTradeRecord);
//      return this.startRefundFlow(originalTradeRecord, refundTradeRecord.getId(), refundTradeRecord.getAmount(), (List)(payRefundDTO != null ? payRefundDTO.getChannelAssignList() : CollUtil.newArrayList(new UnifyRefundDTO.ChannelDetail[0])), (List)(payRefundDTO != null ? payRefundDTO.getDetailList() : CollUtil.newArrayList(new UnifyRefundDTO.Detail[0])), tradeChannels);
//   }
//
//   protected PayCancelVO channelPayCancel(TradeChannelVO tradeChannel, PayCancelDTO payCancelDTO) {
//      this.payCustomBusiness.willChannelPayCancel(payCancelDTO);
//      PayCancelVO cancelResultVO = new PayCancelVO();
//      cancelResultVO.setCode(CancelResultEnum.CANCEL_FAIL.getKey());
//      cancelResultVO.setMsg(CancelResultEnum.CANCEL_FAIL.getDesc());
//      payCancelDTO.setTradeChannelId(tradeChannel.getTradeChannelId());
//      payCancelDTO.setPayType(tradeChannel.getPayType());
//      payCancelDTO.setPayChannel(tradeChannel.getPayChannel());
//      payCancelDTO.setTradeTime(tradeChannel.getTradeTime());
//
//      try {
//         PayService payService = this.channelBusiness.beanOfChannel(tradeChannel.getPayChannel());
//         cancelResultVO = payService.payCancel(payCancelDTO);
//      } catch (Exception var5) {
//         log.error("[渠道支付取消]异常", var5);
//         cancelResultVO.setCode(CancelResultEnum.CANCEL_FAIL_RESET.getKey());
//         cancelResultVO.setMsg(CancelResultEnum.CANCEL_FAIL_RESET.getDesc());
//      }
//
//      log.info("[渠道支付取消]返回结果：{}", cancelResultVO);
//      Integer payState = cancelResultVO.getCode();
//      if (CancelResultEnum.CANCEL_SUCCESS.getKey().equals(payState)) {
//         payState = PayStateEnum.PAY_CLOSE.getKey();
//         this.tradeChannelService.updateTradeRecordChannelState(tradeChannel.getTradeChannelId(), payState, CancelResultEnum.CANCEL_SUCCESS.getDesc(), (String)null, (BigDecimal)null, (JsonNode)null, (LocalDateTime)null);
//      } else {
//         payState = PayStateEnum.PAY_INPROCESS.getKey();
//      }
//
//      cancelResultVO.setPayState(payState);
//      return cancelResultVO;
//   }

   protected TradeChannelVO channelPayRefund(TradeChannelVO originalTradeChannel, PayRefundDTO payRefundDTO, Long refundTradeId) {
      this.payCustomBusiness.willChannelPayRefund(payRefundDTO);
      PayRefundVO payRefundVO = new PayRefundVO();
      payRefundDTO.setTradeChannelId(originalTradeChannel.getTradeChannelId());
      payRefundDTO.setPayType(originalTradeChannel.getPayType());
      payRefundDTO.setPayChannel(originalTradeChannel.getPayChannel());
      payRefundDTO.setOutTradeNo(originalTradeChannel.getOutTradeNo());
      payRefundDTO.setTradeTime(originalTradeChannel.getTradeTime());
      TradeChannel refundTradeChannelEntity = payRefundDTO.convertToTradeChannel(originalTradeChannel, refundTradeId);
      TradeChannelVO refundTradeChannel = TradeChannelVO.of(refundTradeChannelEntity);
      LocalDateTime now = LocalDateTime.now().withNano(0);
      payRefundDTO.setRefundTradeTime(now);
      refundTradeChannelEntity.setTradeTime(now);
      refundTradeChannel.setTradeTime(now);
      if (payRefundDTO.couldSkipChannelRefund()) {
         log.warn("[单渠道退款]跳过渠道退款，直接返回成功");
         refundTradeChannel.setTradeState(PayStateEnum.PAY_SUCC.getKey());
         refundTradeChannel.setTradeResult(PayStateEnum.PAY_SUCC.getDesc());
         return refundTradeChannel;
      } else {
         try {
            this.tradeChannelService.insert(refundTradeChannelEntity);
         } catch (Exception var12) {
            log.error("[单渠道退款]保存记录异常", var12);
            refundTradeChannel.setTradeState(PayStateEnum.PAY_FAIL.getKey());
            refundTradeChannel.setTradeResult(PayStateEnum.PAY_FAIL.getDesc());
            return refundTradeChannel;
         }

         try {
            PayService payService = this.channelBusiness.beanOfChannel(refundTradeChannel.getPayChannel());
            payRefundVO = payService.payRefund(payRefundDTO);
            payRefundVO.setAmount(refundTradeChannel.getAmount());
            if (ObjectUtil.isNull(payRefundVO.getRefundAmount())) {
               payRefundVO.setRefundAmount(payRefundDTO.getRefundAmount());
            }

            log.info("[单渠道退款]返回结果：{}", JacksonUtil.valueToTreeIgnoreNull(payRefundVO));
            refundTradeChannel.fillRefundVO(payRefundVO);
         } catch (ServiceException var10) {
            log.error("[单渠道退款]自定义异常", var10);
            refundTradeChannel.setTradeState(PayStateEnum.PAY_FAIL.getKey());
            refundTradeChannel.setTradeResult(var10.getMessage());
         } catch (Exception var11) {
            log.error("[单渠道退款]异常", var11);
            refundTradeChannel.setTradeState(PayStateEnum.PAY_INPROCESS.getKey());
            refundTradeChannel.setTradeResult(PayStateEnum.PAY_FAIL.getDesc());
         }

         try {
            this.tradeChannelService.updateTradeRecordChannelState(refundTradeChannel.getTradeChannelId(),
                    refundTradeChannel.getTradeState(),
                    refundTradeChannel.getTradeResult(),
                    refundTradeChannel.getOutTradeNo(),
                    null, null, (LocalDateTime)null);
         } catch (Exception var9) {
            log.error("[单渠道退款]渠道结果更新异常", var9);
            payRefundVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
            payRefundVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
         }

         return refundTradeChannel;
      }
   }
//
//   protected RefundSelectVO channelRefundSelect(TradeChannelVO tradeChannel, RefundSelectDTO refundSelectDTO) {
//      refundSelectDTO.setTradeChannelId(tradeChannel.getTradeChannelId());
//      refundSelectDTO.setPayType(tradeChannel.getPayType());
//      refundSelectDTO.setTradeTime(tradeChannel.getTradeTime());
//      RefundSelectVO selectVO = new RefundSelectVO();
//
//      try {
//         PayService payService = this.channelBusiness.beanOfChannel(tradeChannel.getPayChannel());
//         selectVO = payService.refundSelect(refundSelectDTO);
//      } catch (Exception var5) {
//         log.error("[退款查询]异常", var5);
//         selectVO.setCode(PayStateEnum.PAY_INPROCESS.getKey());
//         selectVO.setMsg(PayStateEnum.PAY_INPROCESS.getDesc());
//      }
//
//      log.info("[退款查询]返回结果：{}", JacksonUtil.writeValueAsStringIgnoreNull(selectVO));
//      this.fillVoFields(selectVO, tradeChannel);
//      if (PayStateEnum.PAY_INPROCESS.getKey().equals(selectVO.getCode())) {
//         return selectVO;
//      } else {
//         this.tradeChannelService.updateTradeRecordChannelState(selectVO.getTradeChannelId(), selectVO.getCode(), selectVO.getMsg(), selectVO.getOutTradeNo(), selectVO.getRealAmount(), (JsonNode)null, (LocalDateTime)null);
//         return selectVO;
//      }
//   }

   protected boolean checkRefundAvailable(BigDecimal totalRefundAmount, List<TradeChannelVO> tradeChannels, Map<Long, UnifyRefundDTO.ChannelDetail> channelDTOMap, UnifyRefundVO globalRefundVO) {
      if (tradeChannels.stream().noneMatch((s) -> {
         return PayStateEnum.isPaySuccessState(s.getTradeState());
      })) {
         if (totalRefundAmount.compareTo(BigDecimal.ZERO) == 0) {
            log.error("[渠道退款]无渠道支付成功的0元退款，返回成功");
            globalRefundVO.setCode(PayStateEnum.PAY_SUCC.getKey());
            globalRefundVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
         } else {
            log.error("[渠道退款]无渠道支付成功的明细，失败");
            globalRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            globalRefundVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
         }

         return false;
      } else {
         if (CollUtil.isNotEmpty(channelDTOMap)) {
            Iterator var5 = tradeChannels.iterator();

            while(var5.hasNext()) {
               TradeChannelVO tradeChannel = (TradeChannelVO)var5.next();
               UnifyRefundDTO.ChannelDetail channelDTO = (UnifyRefundDTO.ChannelDetail)channelDTOMap.get(tradeChannel.getTradeChannelId());
               if (channelDTO != null) {
                  if (!PayStateEnum.isPaySuccessState(tradeChannel.getTradeState())) {
                     log.error("[渠道退款]指定渠道不是支付成功状态，tradeChannelId={}", tradeChannel.getTradeChannelId());
                     globalRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
                     globalRefundVO.setMsg("该笔交易明细不允许退款：" + PayStateEnum.getDesc(tradeChannel.getPayType()));
                     return false;
                  }

                  if (channelDTO.getRefundAmount().compareTo(NumberUtil.sub(tradeChannel.getAmount(), tradeChannel.getRefundAmount())) > 0) {
                     log.error("[渠道退款]指定渠道退款金额大于剩余可退金额，tradeChannelId={} 发起金额:{} 总支付金额:{} 已退金额:{}", new Object[]{tradeChannel.getTradeChannelId(), channelDTO.getRefundAmount(), tradeChannel.getAmount(), tradeChannel.getRefundAmount()});
                     globalRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
                     globalRefundVO.setMsg("该笔交易明细不允许退款：" + PayStateEnum.getDesc(tradeChannel.getPayType()));
                     return false;
                  }
               }
            }

            if (LeNumUtil.sumField(channelDTOMap.values(), UnifyRefundDTO.ChannelDetail::getRefundAmount).compareTo(totalRefundAmount) != 0) {
               log.error("[渠道退款]指定渠道退款金额与总退款金额不一致");
               globalRefundVO.setCode(PayStateEnum.PAY_FAIL.getKey());
               globalRefundVO.setMsg("指定渠道退款金额与总退款金额不一致");
               return false;
            }
         }

         return true;
      }
   }

   protected TradeRecord packageRefundTradeInfo(UnifyRefundDTO payRefundDTO, TradeRecord sourceTrade) {
      TradeRecord tradeRecord = new TradeRecord();
      tradeRecord.setId(LeNumUtil.isValidId(payRefundDTO.getRefundTradeId()) ? payRefundDTO.getRefundTradeId() : Id.next());
      tradeRecord.setRelatedTradeId(sourceTrade.getId());
      tradeRecord.setCustId(sourceTrade.getCustId());
      tradeRecord.setAmount(payRefundDTO.getRefundAmount());
      tradeRecord.setTradeType(TradeTypeEnum.isConsumeType(sourceTrade.getTradeType()) ? TradeTypeEnum.CONSUME_REFUND.getKey()
              : TradeTypeEnum.RECHARGE_REFUND.getKey());
      tradeRecord.setTradeState(PayStateEnum.PAY_INPROCESS.getKey());
      tradeRecord.setPayChannel(sourceTrade.getPayChannel());
      tradeRecord.setPayType(sourceTrade.getPayType());
      tradeRecord.setSourceType(sourceTrade.getSourceType());
      tradeRecord.setCanteenId(sourceTrade.getCanteenId());
      tradeRecord.setParam(JacksonUtil.valueToTreeIgnoreNull(payRefundDTO));
      return tradeRecord;
   }
//
//   protected void fillPayCancelDTO(PayCancelDTO cancelDTO, UnifyPayDTO unifyPayDTO) {
//      cancelDTO.setCanteenId(unifyPayDTO.getCanteenId());
//      cancelDTO.setStallId((Long)unifyPayDTO.reduceOrderField(UnifyPayDTO.Order::getStallId, (Object)null));
//      cancelDTO.setMachineSn(unifyPayDTO.getMachineSn());
//      cancelDTO.setCouponId(unifyPayDTO.getCouponId());
//   }

   protected void fillPayRefundDTO(PayRefundDTO refundDTO, UnifyPayDTO unifyPayDTO, TradeRecord tradeRecord) {
      refundDTO.setTradeType(unifyPayDTO.getTradeType());
      refundDTO.setCustId(LeNumUtil.isValidId(unifyPayDTO.getCustId()) ? unifyPayDTO.getCustId() : tradeRecord.getCustId());
      refundDTO.setCustThirdId(unifyPayDTO.getCustThirdId());
      refundDTO.setCanteenId(unifyPayDTO.getCanteenId());
      refundDTO.setStallId(unifyPayDTO.getStallId());
      refundDTO.setMachineSn(unifyPayDTO.getMachineSn());
      if (CollUtil.isNotEmpty(unifyPayDTO.getOrderList())) {
         refundDTO.setMacOrderId(((UnifyPayDTO.Order)unifyPayDTO.getOrderList().get(0)).getMacOrderId());
      } else {
         List<TradeOrderRecharge> tradeOrderRecharges = this.tradeRecordService.queryOrderRechargeTrade(unifyPayDTO.getTradeId());
         if (CollUtil.isNotEmpty(tradeOrderRecharges)) {
            refundDTO.setMacOrderId(((TradeOrderRecharge)tradeOrderRecharges.get(0)).getMacOrderId());
         }
      }

   }
//
//   protected void fillVoFields(RefundSelectVO payVO, TradeChannelVO channelVO) {
//      payVO.setTradeChannelId(channelVO.getTradeChannelId());
//      payVO.setAmount(channelVO.getAmount());
//      if (payVO.getRealAmount() == null && PayStateEnum.isPaidState(payVO.getCode())) {
//         payVO.setRealAmount(payVO.getAmount());
//      }
//
//   }

   protected String tradeNotExistsMsg() {
      return I18n.getMessage("pay.trade-not-exist", new Object[0]);
   }
}
