package com.bonus.core.pay.channel.account.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.constant.LeConstants;
import com.bonus.constant.RetCodeEnum;
import com.bonus.core.account.v3.api.AccBusinessApi;
import com.bonus.core.account.v3.api.AccPayBusinessApi;
import com.bonus.core.account.v3.api.dto.AccOrdBaseDTO;
import com.bonus.core.account.v3.api.dto.AccOrdRefundDTO;
import com.bonus.core.account.v3.web.dto.AccOrdMixPayResultDTO;
import com.bonus.core.account.v3.web.vo.AccOrdBasicsVO;
import com.bonus.core.account.v3.web.vo.AccOrdTradeVO;
import com.bonus.core.allocation.alloc.model.AllocPayModel;
import com.bonus.core.common.constant.NuclearModeEnum;
import com.bonus.core.common.utils.JacksonUtil;
import com.bonus.core.common.utils.LeCodeUtil;
import com.bonus.core.common.utils.LogUtil;
import com.bonus.core.customer.api.CustInfoApi;
import com.bonus.core.customer.dto.CustPayDTO;
import com.bonus.core.order.deprecated.dto.OrdLeCodeDTO;
import com.bonus.core.pay.channel.account.extension.AccPayExtension;
import com.bonus.core.pay.common.constants.*;
import com.bonus.core.pay.common.dto.*;
import com.bonus.core.pay.common.service.PayChannelSelectService;
import com.bonus.core.pay.common.vo.*;
import com.bonus.i18n.I18n;
import com.bonus.utils.id.Id;
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 java.math.BigDecimal;


@Service("AccPayServiceImplExtension")
public class AccPayServiceImpl implements AccPayExtension {
   private static final Logger log = LoggerFactory.getLogger(AccPayServiceImpl.class);
//   @Autowired
//   @Lazy
//   protected TradeChannelService tradeChannelService;
//   @Autowired
//   @Lazy
//   protected CardInfoServiceV4Api cardInfoServiceV4Api;
   @Autowired
   @Lazy
   protected CustInfoApi custInfoApi;
   @Lazy
   @Autowired
   protected AccBusinessApi accBusinessApi;
//   @Autowired
//   @Lazy
//   protected DDService ddService;
//   @Autowired
//   @Lazy
//   protected AlipayAPI alipayAPI;
   @Autowired
   @Lazy
   protected AccPayBusinessApi accPayBusinessApi;
//   @Autowired
//   private AbcPayApi abcPayApi;
//
   public ChannelPayVO channelPayTrail(ChannelPayDTO channelPayDTO) {
      ChannelPayVO channelPayVO = new ChannelPayVO();
      channelPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
      AccOrdBaseDTO accOrdBaseDTO = channelPayDTO.convertToAccPayDTO();
      accOrdBaseDTO.setIfTrialCalculation(true);
      AccOrdBasicsVO accOrdBasicsVO = this.accPayBusinessApi.accPayForOnline(accOrdBaseDTO);
      channelPayVO.setRealAmount(NumberUtil.sub(channelPayDTO.getAmount(), accOrdBasicsVO.getUnpaidBalance()));
      channelPayVO.fillAccOrdBasicsVo(accOrdBasicsVO);
      return channelPayVO;
   }

   public SupportFastAsyncPayVO supportFastAsyncPay(ChannelPayDTO channelPayDTO) {
      return SupportFastAsyncPayVO.yes();
   }

   public ChannelPayVO channelPay(ChannelPayDTO channelPayDTO) {
      ChannelPayVO channelPayVO = new ChannelPayVO();
      channelPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());

      try {
         AccOrdBaseDTO accOrdBaseDTO = channelPayDTO.convertToAccPayDTO();
         LogUtil.info("[账户渠道支付]上传参数", accOrdBaseDTO);
         AccOrdBasicsVO accOrdBasicsVO;
         if (channelPayDTO.isPayForMix()) {
            accOrdBasicsVO = this.accPayBusinessApi.accPayForMixPay(accOrdBaseDTO);
            if (RetCodeEnum.SUCC.getKey().equals(accOrdBasicsVO.getCode())) {
               AccOrdMixPayResultDTO accOrdMixPayResultDTO = this.packageAccOrdMixPayResultDTO(accOrdBaseDTO, accOrdBasicsVO, channelPayDTO.getTradeChannelId());
               channelPayVO.setChannelParam(JacksonUtil.valueToTree(accOrdMixPayResultDTO));
            }
         } else if (channelPayDTO.isDeviceOffline()) {
            accOrdBasicsVO = this.accPayBusinessApi.accPayForOffline(accOrdBaseDTO);
         } else {
            accOrdBasicsVO = this.accPayBusinessApi.accPayForOnline(accOrdBaseDTO);
            AndroidPayDTO androidPayDTO = channelPayDTO.convertToAndroidPayDTO();
            Integer payType = androidPayDTO.getPayType();
            if (PayTypeEnum.ABC_PAY_CODE.getKey().equals(payType) || PayTypeEnum.ABC_ID_CODE.getKey().equals(payType)) {
//               this.abcPayApi.abcOrderDataUpload(androidPayDTO); // 这个是原始代码
               throw new ServiceException("[账户渠道支付]异常"); // 这个是dgw改的代码 2025 02 19
            }
         }

         LogUtil.info("[账户渠道支付]返回结果", accOrdBasicsVO);
         if (!RetCodeEnum.SUCC.getKey().equals(accOrdBasicsVO.getCode())) {
            channelPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());
            channelPayVO.setMsg(RetCodeEnum.PAY_BALANCE_NO_ENOUGH.getKey().equals(accOrdBasicsVO.getCode()) ? I18n.getMessage("acc_not_enough_amount", new Object[0]) : PayStateEnum.PAY_FAIL.getDesc());
            channelPayVO.setRealAmount(BigDecimal.ZERO);
         } else {
            channelPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
            channelPayVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
            channelPayVO.setRealAmount(NumberUtil.sub(channelPayDTO.getAmount(), accOrdBasicsVO.getUnpaidBalance()));
         }

         channelPayVO.setCustId(channelPayDTO.getCustId());
         channelPayVO.setAmount(channelPayDTO.getAmount());
         channelPayVO.setPayChannel(PayChannelEnum.ACC.getKey());
         channelPayVO.fillAccOrdBasicsVo(accOrdBasicsVO);
      } catch (ServiceException var7) {
         log.info("[账户渠道支付]自定义异常", var7);
         channelPayVO.setMsg(var7.getMessage());
      } catch (Exception var8) {
         log.error("[账户渠道支付]异常", var8);
         channelPayVO.setMsg("账户支付异常");
      }

      return channelPayVO;
   }

   public AndroidPayVO paySelect(PaySelectDTO paySelectDTO) {
      log.info("[账户]查询支付结果_上传参数：{}", JacksonUtil.writeValueAsStringIgnoreNull(paySelectDTO));
      AndroidPayVO androidPayVO = new AndroidPayVO();
      androidPayVO.setCode(PayStateEnum.PAY_FAIL.getKey());

      try {
         AccOrdTradeVO accOrdTradeVO = this.accBusinessApi.queryTradeDetailByOrderId(paySelectDTO.getTradeChannelId());
         androidPayVO.setCode(PayStateEnum.PAY_SUCC.getKey());
         androidPayVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
         androidPayVO.setAmount(accOrdTradeVO.getAmount());
         androidPayVO.setRealAmount(accOrdTradeVO.getAmount());
         androidPayVO.setPayChannel(PayChannelEnum.ACC.getKey());
         androidPayVO.setPersonalPay(accOrdTradeVO.getWalletPay());
         androidPayVO.setSubsidyReduce(accOrdTradeVO.getSubsidyPay());
         androidPayVO.setRedEnvelopeReduce(accOrdTradeVO.getRedEnvelopePay());
         androidPayVO.setWalletBal(accOrdTradeVO.getWalletBal());
         androidPayVO.setSubsidyBal(accOrdTradeVO.getSubBal());
         androidPayVO.setRedEnvelope(accOrdTradeVO.getRedBal());
         androidPayVO.setAccBal(accOrdTradeVO.getAccBal());
      } catch (ServiceException var4) {
         log.info("[账户]设备端查询支付结果自定义异常", var4);
         androidPayVO.setMsg(var4.getMessage());
      } catch (Exception var5) {
         log.error("[账户]设备端查询支付结果异常", var5);
         androidPayVO.setMsg("账户查询支付结果异常");
      }

      androidPayVO.setTradeId(paySelectDTO.getTradeChannelId());
      return androidPayVO;
   }

   public PayCancelVO payCancel(PayCancelDTO payCancelDTO) {
      log.info("[账户]取消支付_上传参数:{}", JacksonUtil.writeValueAsStringIgnoreNull((PayCancelDTO)payCancelDTO));
      PayCancelVO payCancelVO = new PayCancelVO();
      payCancelVO.setCode(PayStateEnum.PAY_FAIL.getKey());
      payCancelVO.setMsg(PayStateEnum.PAY_FAIL.getDesc());
      return payCancelVO;
   }

   public PayRefundVO payRefund(PayRefundDTO payRefundDTO) {
      log.info("[账户]支付退款_上传参数：{}", JacksonUtil.writeValueAsStringIgnoreNull(payRefundDTO));
      AccOrdRefundDTO accOrdRefundDTO = this.packageAccOrdRefundDTO(payRefundDTO);
      PayRefundVO payRefundtVO = new PayRefundVO();
      payRefundtVO.setCode(PayStateEnum.PAY_FAIL.getKey());

      try {
         AccOrdBasicsVO accOrdBasicsVO = this.accPayBusinessApi.accOrdForRefund(accOrdRefundDTO);
         payRefundtVO.setCode(PayStateEnum.PAY_SUCC.getKey());
         payRefundtVO.setMsg(PayStateEnum.PAY_SUCC.getDesc());
         payRefundtVO.setTradeId(payRefundDTO.getRefundTradeChannelId());
         payRefundtVO.setAmount(payRefundDTO.getAmount());
         payRefundtVO.setRefundAmount(payRefundDTO.getRefundAmount());
         payRefundtVO.setOutTradeNo(ObjectUtil.isNotNull(accOrdBasicsVO) ? String.valueOf(accOrdBasicsVO.getAccTradeId()) : null);
         payRefundtVO.fillAccOrdBasicsVo(accOrdBasicsVO);
      } catch (ServiceException var5) {
         log.info("[账户]支付退款自定义异常", var5);
         payRefundtVO.setMsg(var5.getMessage());
      } catch (Exception var6) {
         log.error("[账户]支付退款异常", var6);
         payRefundtVO.setMsg("账户支付退款异常");
      }

      return payRefundtVO;
   }

   public MixPayResultVO mixPayResultHandler(MixPayResultDTO mixPayResultDTO, TradeChannelVO tradeChannelVO) {
      MixPayResultVO resultVO = MixPayResultVO.newDefaultInstance();
      if (tradeChannelVO.getParam() == null) {
         return resultVO;
      } else if (!PayStateEnum.isPaySuccessState(tradeChannelVO.getTradeState())) {
         return resultVO;
      } else if (!PayStateEnum.isFinishedState(mixPayResultDTO.getCode())) {
         return resultVO;
      } else {
         AccOrdMixPayResultDTO accOrdMixPayResultDTO = (AccOrdMixPayResultDTO)JacksonUtil.treeToValue(tradeChannelVO.getParam(), AccOrdMixPayResultDTO.class);
         if (accOrdMixPayResultDTO == null) {
            return resultVO;
         } else {
            if (PayStateEnum.isPaidState(mixPayResultDTO.getCode())) {
               accOrdMixPayResultDTO.setDealState(PayDealStateEnum.SUCC.getKey());
               tradeChannelVO.setTradeState(PayStateEnum.PAY_SUCC.getKey());
               tradeChannelVO.setTradeResult(PayStateEnum.PAY_SUCC.getDesc());
            } else if (PayStateEnum.isCloseState(mixPayResultDTO.getCode())) {
               accOrdMixPayResultDTO.setDealState(PayDealStateEnum.ONLINE_FAIL.getKey());
               tradeChannelVO.setTradeState(PayStateEnum.PAY_CLOSE.getKey());
               tradeChannelVO.setTradeResult(PayStateEnum.PAY_CLOSE.getDesc());
            } else if (LeConstants.COMMON_YES.equals(accOrdMixPayResultDTO.getIfOnline())) {
               accOrdMixPayResultDTO.setDealState(PayDealStateEnum.ONLINE_FAIL.getKey());
               tradeChannelVO.setTradeState(PayStateEnum.PAY_FAIL.getKey());
               tradeChannelVO.setTradeResult(PayStateEnum.PAY_FAIL.getDesc());
            } else {
               accOrdMixPayResultDTO.setDealState(PayDealStateEnum.OFFLINE_FAIL.getKey());
               tradeChannelVO.setTradeState(PayStateEnum.PAY_SUCC.getKey());
               tradeChannelVO.setTradeResult(PayStateEnum.PAY_SUCC.getDesc());
               tradeChannelVO.setAmount(tradeChannelVO.getAmount().add(mixPayResultDTO.getUnpaidBalance()));
            }

            try {
               AccOrdBasicsVO accOrdBasicsVO = this.accPayBusinessApi.accPayForMixPayResult(accOrdMixPayResultDTO);
               resultVO.fillAccOrdBasicsVo(accOrdBasicsVO);
               resultVO.setNeedUpdateTradeChannel(true);
            } catch (Exception var6) {
               log.error("[混合支付回调]处理账户混合支付结果错误 {} {}", var6.getMessage(), JacksonUtil.writeValueAsString(accOrdMixPayResultDTO));
            }

            return resultVO;
         }
      }
   }

   public boolean payChannelSelect(PayChannelSelectEnum selectType, PayChannelSelectDTO payChannelSelectDTO, AllocPayModel canteenPayModel, AllocPayModel merchantPayModel, PayChannelSelectService payChannelSelectService, PayChannelSelectResultVO resultVO) {
      if (PayChannelSelectEnum.isRecharge(selectType.getKey())) {
         return true;
      } else {
         if (PayChannelSelectEnum.DEVICE_CONSUME != selectType && PayChannelSelectEnum.DEVICE_OFFLINE_CONSUME != selectType && PayChannelSelectEnum.OPEN_CONSUME != selectType && PayChannelSelectEnum.PAD_CONSUME != selectType) {
            if (PayChannelSelectEnum.MOBILE_CONSUME == selectType && payChannelSelectDTO.ifEqualPayType(PayTypeEnum.MEAL_CARD, PayTypeEnum.ACC_SCAN)) {
               resultVO.addPayChannelSplit(payChannelSelectDTO.getPayType(), PayChannelEnum.ACC.getKey());
            }
         } else if (!NuclearModeEnum.isCard(payChannelSelectDTO.getNuClearMode()) && !NuclearModeEnum.isFace(payChannelSelectDTO.getNuClearMode())) {
            if (NuclearModeEnum.NUCLEAR_MODE_QRCODE.getKey().equals(payChannelSelectDTO.getNuClearMode())) {
               if (LeCodeUtil.isLeCode(payChannelSelectDTO.getAuthCode())) {
                  OrdLeCodeDTO ordLeCodeDTO = LeCodeUtil.readLeCode(payChannelSelectDTO.getAuthCode());
                  if (ordLeCodeDTO.ifPersonalPay()) {
                     resultVO.addPayChannelSplit(PayTypeEnum.OTHER_QRCODE.getKey(), PayChannelEnum.ACC.getKey());
                     if (resultVO.getCustPayVO() == null) {
                        resultVO.setErrorInfo(LeRetCodeEnum.PAY_PERSONAL_NO_EXIT);
                     }
                  }
               } else if (LeCodeUtil.isDingDingCode(payChannelSelectDTO.getAuthCode())) {
//                  if (resultVO.getCustPayVO() == null) {
//                     try {
//                        DingTalkQrCodeResp ddCodeResp = this.handlerDingbadgeCode(payChannelSelectDTO.getAuthCode());
//                        resultVO.setCustPayVO(this.custInfoApi.getCustPayVO((new CustPayDTO()).setCustId(ddCodeResp.getCustId())));
//                     } catch (Exception var8) {
//                        resultVO.setErrorInfo(var8);
//                     }
//                  } 2025-02-19 dgw 注释掉
//
//                  resultVO.addPayChannelSplit(PayTypeEnum.ALI_DING_ACC_PAY.getKey(), PayChannelEnum.ACC.getKey());
               }
            } else if (PayChannelSelectEnum.DEVICE_OFFLINE_CONSUME == selectType && PayTypeEnum.MEAL_CARD.getKey().equals(payChannelSelectDTO.getPayType())) {
               resultVO.addPayChannelSplit(PayTypeEnum.MEAL_CARD.getKey(), PayChannelEnum.ACC.getKey());
            }
         } else {
            resultVO.addPayChannelSplit(PayTypeEnum.MEAL_CARD.getKey(), PayChannelEnum.ACC.getKey());
            if (resultVO.getCustPayVO() == null) {
               resultVO.setErrorInfo(LeRetCodeEnum.PAY_PERSONAL_NO_EXIT);
            }
         }

         return true;
      }
   }

//   protected DingTalkQrCodeResp handlerDingbadgeCode(String authCode) {
//      LogUtil.printArgsIn("handlerDingbadgeCode", authCode);
//      DingTalkQrCodeReq dingCodeReq = new DingTalkQrCodeReq();
//      dingCodeReq.setOrdId(Id.nextString());
//      dingCodeReq.setAuthCode(authCode);
//      DingTalkQrCodeResp dingCodeRes = this.ddService.dingTalkDecodeCode(dingCodeReq);
//      log.info("[设备收单支付]钉工牌二维码解码返回信息{}", JSONUtil.toJsonStr(dingCodeRes));
//      if (ObjectUtil.isNotNull(dingCodeRes)) {
//         if (!ObjectUtil.isNull(dingCodeRes.getCustId()) && !LeConstants.DATA_DEFAULT_LONG.equals(dingCodeRes.getCustId())) {
//            LogUtil.printArgsOut("handlerDingbadgeCode", dingCodeRes);
//            return dingCodeRes;
//         } else {
//            throw new ServiceException(I18n.getMessage("order.mac.code-unbind-dingding", new Object[0]));
//         }
//      } else {
//         throw new ServiceException(I18n.getMessage("order.mac.code-parse-failed", new Object[0]));
//      }
//   }

   protected AccOrdRefundDTO packageAccOrdRefundDTO(PayRefundDTO payRefundDTO) {
      AccOrdRefundDTO accOrdRefundDTO = new AccOrdRefundDTO();
      accOrdRefundDTO.setAmount(payRefundDTO.getRefundAmount());
      accOrdRefundDTO.setCustId(payRefundDTO.getCustId());
      accOrdRefundDTO.setOrderId(payRefundDTO.getTradeId());
      accOrdRefundDTO.setRefundOrderId(payRefundDTO.getRefundTradeId());
      accOrdRefundDTO.setCanteenId(payRefundDTO.getCanteenId());
      accOrdRefundDTO.setCanteenName(payRefundDTO.getCanteenName());
      accOrdRefundDTO.setShopstallId(payRefundDTO.getStallId());
      accOrdRefundDTO.setShopstallName(payRefundDTO.getStallName());
      accOrdRefundDTO.setNuClearMode(payRefundDTO.getNuClearMode());
      return accOrdRefundDTO;
   }

   protected AccOrdMixPayResultDTO packageAccOrdMixPayResultDTO(AccOrdBaseDTO accOrdBaseDTO, AccOrdBasicsVO accOrdBasicsVO, Long tradeChannelId) {
      AccOrdMixPayResultDTO payResultDTO = (AccOrdMixPayResultDTO) BeanUtil.copyProperties(accOrdBaseDTO, AccOrdMixPayResultDTO.class, new String[0]);
      payResultDTO.setUnpaidBalance(accOrdBasicsVO.getUnpaidBalance());
      payResultDTO.setOrderId(tradeChannelId);
      return payResultDTO;
   }
}
