package org.springblade.yeePay.service;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.SystemConstant;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.guosen.bussiness.entity.Bussiness;
import org.springblade.modules.guosen.bussiness.entity.BussinessDebit;
import org.springblade.modules.guosen.bussiness.excel.WithdrawRequestExcel;
import org.springblade.modules.guosen.bussiness.service.IBussinessDebitService;
import org.springblade.modules.guosen.bussiness.service.IBussinessService;
import org.springblade.modules.guosen.bussinessInfo.entity.BussinessInfo;
import org.springblade.modules.guosen.bussinessRateStrategy.service.IBussinessRateStrategyService;
import org.springblade.modules.guosen.bussinessRegisterRequest.entity.BussinessRegisterRequest;
import org.springblade.modules.guosen.bussinessRegisterRequest.service.IBussinessRegisterRequestService;
import org.springblade.modules.guosen.bussinessTransferOrder.entity.BussinessTransferOrder;
import org.springblade.modules.guosen.bussinessTransferOrder.service.IBussinessTransferOrderService;
import org.springblade.modules.guosen.bussinessuserinfo.entity.BussinessUserInfo;
import org.springblade.modules.guosen.bussinessuserinfo.service.IBussinessUserInfoService;
import org.springblade.modules.guosen.bussinessuserwithdraw.entity.BussinessUserWithdraw;
import org.springblade.modules.guosen.bussinessuserwithdraw.service.IBussinessUserWithdrawService;
import org.springblade.modules.guosen.productratestrategy.entity.ProductRateStrategy;
import org.springblade.modules.guosen.productratestrategy.service.IProductRateStrategyService;
import org.springblade.modules.system.service.IParamService;
import org.springblade.yeePay.entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

@Service
@Slf4j
public class BussinessPayService {

    @Autowired
    private YeePayService yeePayService;
    @Autowired
    private IBussinessTransferOrderService bussinessTransferOrderService;
    @Autowired
    private IBussinessDebitService bussinessDebitService;
    @Autowired
    private IBussinessUserWithdrawService withdrawService;
    @Autowired
    private IParamService paramService;
    @Autowired
    private IBussinessUserInfoService userInfoService;
    @Autowired
    private IBussinessRegisterRequestService bussinessRegisterRequestService;
    @Autowired
    private IBussinessService bussinessService;

    /**
     * 商户间转账
     * 适用于：子商户发起代付前转账到平台商、子商户充值后转账服务费到平台商
     *
     * @param bussinessTransferOrder
     * @return
     */
    public R transferOrder(BussinessTransferOrder bussinessTransferOrder, String parentMerchantNo) {
        TransferOrderDto transferOrderDto = TransferOrderDto.builder()
                .fromMerchantNo(bussinessTransferOrder.getFromMerchantNo())
                .toMerchantNo(bussinessTransferOrder.getToMerchantNo())
                .orderAmount(bussinessTransferOrder.getOrderAmount())
                .requestNo(bussinessTransferOrder.getRequestNo())
                .feeChargeSide(bussinessTransferOrder.getFeeChargeSide())
                .usage(StringUtil.isBlank(bussinessTransferOrder.getTransferUsage()) ? "采购" : bussinessTransferOrder.getTransferUsage())
                .build();
        R result = yeePayService.transferOrder(transferOrderDto, parentMerchantNo);
        JSONObject data = JSONUtil.parseObj(result.getData());
        String requestNo = data.getStr("requestNo");
        String fromMerchantNo = data.getStr("fromMerchantNo");
        String returnCode = data.getStr("returnCode");
        String transferStatus = data.getStr("transferStatus");
        if (returnCode.equals("UA00000")) { //转账成功
            BussinessTransferOrder dbTransferOrder = this.bussinessTransferOrderService.getByRequestNo(requestNo, fromMerchantNo);
            dbTransferOrder.setThirdLog(JSONUtil.toJsonStr(data));
            dbTransferOrder.setFee(data.getStr("fee"));
            dbTransferOrder.setOrderNo(data.getStr("orderNo"));
            dbTransferOrder.setFinishTime(data.getStr("finishTime"));
            dbTransferOrder.setDebitAmount(data.getStr("debitAmount"));
            dbTransferOrder.setFeeMerchantNo(data.getStr("feeMerchantNo"));
            dbTransferOrder.setReceiveAmount(data.getStr("receiveAmount"));
            if ("REQUEST_RECEIVE".equals(transferStatus)) {
                dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.REQUEST_RECEIVE.getValue());
                bussinessTransferOrderService.updateById(dbTransferOrder);
                return R.success("REQUEST_RECEIVE");
            } else if ("SUCCESS".equals(transferStatus)) {
                dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.SUCCESS.getValue());
                this.bussinessTransferOrderService.updateById(dbTransferOrder);
                return R.success("SUCCESS");
            } else if ("FAIL".equals(transferStatus)) {
                dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.FAIL.getValue());
                dbTransferOrder.setReturnMsg(data.getStr("returnMsg"));
                bussinessTransferOrderService.updateById(dbTransferOrder);
                return R.fail(data.getStr("returnMsg"));
            }
        } else {
            log.error("=================转账请求响应转账下单失败====================");
            log.error("转账请求号：" + requestNo + ", 转出商户号：" + fromMerchantNo + ", 失败原因：" + data.getStr("returnMsg"));
            bussinessTransferOrder.setReturnMsg(data.getStr("returnMsg"));
            bussinessTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.FAIL.getValue());
            bussinessTransferOrder.setThirdLog(JSONUtil.toJsonStr(data));
            bussinessTransferOrderService.updateById(bussinessTransferOrder);
            return R.fail(data.getStr("returnMsg"));
        }
        return R.status(true);
    }

    /**
     * 调试专用
     * 商户间转账
     * 适用于：子商户发起代付前转账到平台商、子商户充值后转账服务费到平台商
     *
     * @param bussinessTransferOrder
     * @return
     */
    public R transferOrderDebug(BussinessTransferOrder bussinessTransferOrder, String parentMerchantNo) {
        TransferOrderDto transferOrderDto = TransferOrderDto.builder()
                .fromMerchantNo(bussinessTransferOrder.getFromMerchantNo())
                .toMerchantNo(bussinessTransferOrder.getToMerchantNo())
                .orderAmount(bussinessTransferOrder.getOrderAmount())
                .requestNo(bussinessTransferOrder.getRequestNo())
                .feeChargeSide(bussinessTransferOrder.getFeeChargeSide())
                .usage(StringUtil.isBlank(bussinessTransferOrder.getTransferUsage()) ? "采购" : bussinessTransferOrder.getTransferUsage())
                .build();
        R result = yeePayService.transferOrder(transferOrderDto, parentMerchantNo);
        JSONObject data = JSONUtil.parseObj(result.getData());
        String requestNo = data.getStr("requestNo");
        String fromMerchantNo = data.getStr("fromMerchantNo");
        BussinessTransferOrder dbTransferOrder = this.bussinessTransferOrderService.getByRequestNo(requestNo, fromMerchantNo);
        if (dbTransferOrder == null) {
            log.error("=================转账请求响应，转账订单不存在====================");
            log.error("转账请求号：" + requestNo + ", 转出商户号：" + fromMerchantNo);
            return R.fail("TF订单查询失败");
        }
        String returnCode = data.getStr("returnCode");
        String transferStatus = data.getStr("transferStatus");
        dbTransferOrder.setThirdLog(JSONUtil.toJsonStr(data));
        if (returnCode.equals("UA00000")) { //转账成功
            dbTransferOrder.setFee(data.getStr("fee"));
            dbTransferOrder.setOrderNo(data.getStr("orderNo"));
            dbTransferOrder.setFinishTime(data.getStr("finishTime"));
            dbTransferOrder.setDebitAmount(data.getStr("debitAmount"));
            dbTransferOrder.setFeeMerchantNo(data.getStr("feeMerchantNo"));
            dbTransferOrder.setReceiveAmount(data.getStr("receiveAmount"));
            if ("REQUEST_RECEIVE".equals(transferStatus)) {
                dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.REQUEST_RECEIVE.getValue());
                bussinessTransferOrderService.updateById(dbTransferOrder);
                return R.status(true);
            } else if ("SUCCESS".equals(transferStatus)) {
                return R.status(true);
            } else if ("FAIL".equals(transferStatus)) {
                dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.FAIL.getValue());
                dbTransferOrder.setReturnMsg(data.getStr("returnMsg"));
                bussinessTransferOrderService.updateById(dbTransferOrder);
                return R.fail(data.getStr("returnMsg"));
            }
        } else {
            log.error("=================充值服务费转账请求响应转账下单失败====================");
            log.error("转账请求号：" + requestNo + ", 转出商户号：" + fromMerchantNo + ", 失败原因：" + data.getStr("returnMsg"));
            dbTransferOrder.setReturnMsg(data.getStr("returnMsg"));
            dbTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.FAIL.getValue());
            dbTransferOrder.setThirdLog(JSONUtil.toJsonStr(data));
            bussinessTransferOrderService.updateById(dbTransferOrder);
            return R.fail(data.getStr("returnMsg"));
        }
        return R.status(true);
    }


    /**
     * 代付
     * 只适用于平台商代付
     *
     * @param debitId
     * @return
     */
    @Async
    public R payOrder(Long debitId, String parentMerchantNo) {
        BussinessDebit debit = this.bussinessDebitService.getById(debitId);
        if (debit != null) {
            String requestNo = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
            debit.setRequestNo(requestNo);
            boolean save = bussinessDebitService.updateById(debit);
            if (save) {
                PayOrderDto payOrderDto = new PayOrderDto();
                payOrderDto.setOrderAmount(debit.getPrice().doubleValue());
                payOrderDto.setReceiveType("REAL_TIME");
                payOrderDto.setFeeChargeSide("PAYER");
                payOrderDto.setReceiverAccountNo(debit.getReceiverAccountNo());
                payOrderDto.setReceiverAccountName(debit.getReceiverAccountName());
                payOrderDto.setReceiverBankCode(debit.getReceiverBankCode());
                payOrderDto.setBankAccountType(debit.getBankAccountType());
                payOrderDto.setRequestNo(debit.getRequestNo());
                R result = this.yeePayService.payOrder(payOrderDto, parentMerchantNo);
                if (result.isSuccess()) {
                    JSONObject data = JSONUtil.parseObj(result.getData());
                    String returnCode = data.getStr("returnCode");
                    String returnMsg = data.getStr("returnMsg");
                    String orderNo = data.getStr("orderNo");
                    String msg = returnMsg;
                    debit.setThirdPayLog(JSONUtil.toJsonStr(data));
                    if (StringUtil.isNotBlank(returnCode) && returnCode.equals("UA00000")) { //代付发起成功
                        log.info("========================单笔代付发起成功====================");
                        debit.setThirdOrderNo(orderNo);
                        bussinessDebitService.updateById(debit);
                        return R.data(data, msg);
                    } else {
                        log.error("========================单笔代付发起失败====================");
                        log.error(msg);
                        debit.setStatus(SystemConstant.BussinessDebitStatus.FAIL.getValue());
                        debit.setFreeze("0.00");
                        debit.setFailReason(msg);
                        bussinessDebitService.updateById(debit);
                        return R.data(400, data, msg);
                    }
                } else {
                    log.error("========================单笔代付发起失败====================");
                    log.error(result.getMsg());
                    debit.setFreeze("0.00");
                    bussinessDebitService.updateById(debit);
                    return R.fail(result.getMsg());
                }
            } else {
                log.error("==================代付账单请求号保存失败========================");
                return R.fail("代付账单请求号保存失败");
            }
        } else {
            log.error("==================代付账单不存在========================");
            return R.fail("代付账单不存在");
        }
    }

    public R withdrawOrder(BussinessUserWithdraw withdraw, String parentMerchantNo) {
        WithdrawOrderDto withdrawOrderDto = WithdrawOrderDto.builder()
                .orderAmount(withdraw.getOrderAmount().doubleValue())
                .bankAccountNo(withdraw.getBankAccountNo())
                .merchantNo(withdraw.getMerchantNo())
                .receiveType(withdraw.getReceiveType())
                .requestNo(withdraw.getRequestNo())
                .build();
        R result = yeePayService.withdrawOrder(withdrawOrderDto, parentMerchantNo);
        JSONObject data = JSONUtil.parseObj(result.getData());
        String status = data.getStr("status");
        String orderNo = data.getStr("orderNo");
        String returnCode = data.getStr("returnCode");
        withdraw.setThirdLog(JSONUtil.toJsonStr(data));
        if (returnCode.equals("UA00000")) { //转账成功
            log.info("====================提现发起成功===========================");
            withdraw.setThirdOrderNo(orderNo);
            withdraw.setReturnMsg("提现发起成功");
            if ("REQUEST_RECEIVE".equals(status)) {
                withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.REQUEST_RECEIVE.getValue());
                withdrawService.updateById(withdraw);
                return R.status(true);
            } else if ("REQUEST_ACCEPT".equals(status)) {
                withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.REQUEST_ACCEPT.getValue());
                withdrawService.updateById(withdraw);
                return R.status(true);
            } else if ("REMITING".equals(status)) {
                withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.REMITING.getValue());
                withdrawService.updateById(withdraw);
                return R.status(true);
            } else if ("FAIL".equals(status)) {
                withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.FAIL.getValue());
                withdraw.setFailReason(data.getStr("returnMsg"));
                withdraw.setReturnMsg(data.getStr("returnMsg"));
                withdrawService.updateById(withdraw);
                return R.fail(data.getStr("returnMsg"));
            } else {
                withdraw.setFailReason(data.getStr("returnMsg"));
                withdraw.setReturnMsg(data.getStr("returnMsg"));
                withdrawService.updateById(withdraw);
                return R.success(data.getStr("returnMsg"));
            }
        } else {
            log.info("====================提现发起失败===========================");
            log.error("提现请求号：" + withdraw.getRequestNo() + ", 提现商户号：" + withdraw.getMerchantNo() + ", 失败原因：" + data.getStr("returnMsg"));
            withdraw.setFailReason(data.getStr("returnMsg"));
            withdraw.setReturnMsg(data.getStr("returnMsg"));
            withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.FAIL.getValue());
            withdrawService.updateById(withdraw);
            return R.fail(data.getStr("returnMsg"));
        }
    }


    public void handleFirstTransferScene(Long firstTransferOrderId) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                BussinessTransferOrder firstTransferOrder = bussinessTransferOrderService.getById(firstTransferOrderId);
                if (firstTransferOrder.getTransferStatus().intValue() == SystemConstant.TransferOrderStatus.REQUEST_RECEIVE.getValue()) {
                    try {
                        R result = bussinessTransferOrderService.transferQuery(firstTransferOrder.getId());
                        if (result.isSuccess()) {
                            if (result.getData().equals("SUCCESS")) {
                                String withdrawRate = paramService.getValue("yee_withdraw_rate");
                                BussinessUserWithdraw withdraw = withdrawService.getByFirstTransferOrderId(firstTransferOrderId);
                                BussinessTransferOrder secondTransferOrder = new BussinessTransferOrder();
                                secondTransferOrder.setFromMerchantNo(firstTransferOrder.getToMerchantNo());
                                secondTransferOrder.setToMerchantNo(withdraw.getMerchantNo());
                                secondTransferOrder.setTransferUsage("提现前转账");
                                secondTransferOrder.setOrderAmount((withdraw.getOrderAmount().add(new BigDecimal(withdrawRate))).toString());
                                secondTransferOrder.setFeeChargeSide("OUTSIDE");
                                secondTransferOrder.setRequestNo(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
                                secondTransferOrder.setTransferScene(SystemConstant.TransferScene.FOR_WITHDRAW_SECOND_TRANSFER.getValue());
                                secondTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.WAIT.getValue());
                                bussinessTransferOrderService.save(secondTransferOrder);
                                withdraw.setSecondTransferOrderId(secondTransferOrder.getId());
                                withdrawService.updateById(withdraw);
                                R secondTransferResult = transferOrder(secondTransferOrder, firstTransferOrder.getToMerchantNo());
                                if (secondTransferResult.isSuccess()) {
                                    if (secondTransferResult.getMsg().equals("REQUEST_RECEIVE")) {
                                        handleSecondTransferScene(secondTransferOrder.getId());
                                    } else if (secondTransferResult.getMsg().equals("SUCCESS")) {
                                        withdrawOrder(withdraw, secondTransferOrder.getFromMerchantNo());
                                    }
                                } else {
                                    withdraw.setFailReason("代付失败");
                                    withdraw.setReturnMsg(secondTransferResult.getMsg());
                                    withdrawService.updateById(withdraw);
                                }
                                this.cancel();
                                timer.cancel();
                            }
                        }
                    } catch (Exception e) {
                        this.cancel();
                        timer.cancel();
                    }
                } else {
                    this.cancel();
                    timer.cancel();
                }
            }
        }, 500, 10000);
    }

    public void handleSecondTransferScene(Long secondTransferOrderId) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                BussinessTransferOrder firstTransferOrder = bussinessTransferOrderService.getById(secondTransferOrderId);
                if (firstTransferOrder.getTransferStatus().intValue() == SystemConstant.TransferOrderStatus.REQUEST_RECEIVE.getValue()) {
                    try {
                        R result = bussinessTransferOrderService.transferQuery(secondTransferOrderId);
                        if (result.isSuccess()) {
                            if (result.getData().equals("SUCCESS")) {
                                BussinessUserWithdraw withdraw = withdrawService.getBySecondTransferOrderId(secondTransferOrderId);
                                Long userInfoId = withdraw.getUserInfoId();
                                BussinessUserInfo userInfo = userInfoService.getById(userInfoId);
                                withdraw.setReturnMsg("提现前第二次转账成功");
                                withdrawOrder(withdraw, userInfo.getParentMerchantNo());
                                this.cancel();
                                timer.cancel();
                            }
                        }else{
                            this.cancel();
                            timer.cancel();
                        }
                    } catch (Exception e) {
                        this.cancel();
                        timer.cancel();
                    }
                } else {
                    this.cancel();
                    timer.cancel();
                }
            }
        }, 500, 10000);
    }

    private BussinessUserInfo toUserInfoFromImport(WithdrawRequestExcel excel, Long bussinessId) {
        BussinessUserInfo userInfo = new BussinessUserInfo();
        userInfo.setUserName(excel.getUserName());
        userInfo.setUserPhone(excel.getUserPhone());
        userInfo.setUserShortName(excel.getUserName());
        userInfo.setUserLicenceNo(excel.getUserLicenceNo());
        userInfo.setUserLicenceType("ID_CARD");
        userInfo.setUserCardFrontUrl(excel.getUserCardFrontUrl());
        userInfo.setUserCardBackUrl(excel.getUserCardBackUrl());
        userInfo.setThirdUserCardBackUrl(excel.getUserCardBackUrl());
        userInfo.setBankCode(excel.getBankCode());
        userInfo.setBankCardNo(excel.getBankCardNo());
        userInfo.setBankAccountType("DEBIT_CARD");
        userInfo.setBussinessId(bussinessId);
        return userInfo;
    }

    /**
     * 提现前发起第一次转账到平台商
     *
     * @param userInfo
     * @param merchantNo
     * @param excel
     * @return
     */
    private R<Long> transferOrderToPlatform(BussinessUserInfo userInfo, String merchantNo, WithdrawRequestExcel excel) {
        String withdrawRate = paramService.getValue("yee_withdraw_rate");
        String transferRate = paramService.getValue("yee_transfer_rate");
        DecimalFormat transferDecimalFormat = new DecimalFormat("0.00");
        BigDecimal orderAmount = new BigDecimal(transferDecimalFormat.format(excel.getOrderAmount()));
        BigDecimal withdrawFee = new BigDecimal(withdrawRate);
        BigDecimal transferFee = new BigDecimal(transferRate);
        BigDecimal transferAmount = orderAmount.add(withdrawFee).add(transferFee);
        BussinessTransferOrder firstTransferOrder = new BussinessTransferOrder();
        firstTransferOrder.setFromMerchantNo(merchantNo);
        firstTransferOrder.setToMerchantNo(userInfo.getParentMerchantNo());
        firstTransferOrder.setTransferUsage("提现前转账到平台商");
        firstTransferOrder.setOrderAmount(transferAmount.toString());
        firstTransferOrder.setFeeChargeSide("OUTSIDE");
        firstTransferOrder.setRequestNo(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
        firstTransferOrder.setTransferScene(SystemConstant.TransferScene.FOR_WITHDRAW_FIRST_TRANSFER.getValue());
        firstTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.WAIT.getValue());
        this.bussinessTransferOrderService.save(firstTransferOrder);
        R<BussinessUserWithdraw> withDrawOrderResult = this.createWithDrawOrder(userInfo, firstTransferOrder.getId(), null, null, orderAmount, "受理成功，请等待结果", "提现前第一次转账发起受理成功", null);
        if (withDrawOrderResult.isSuccess()) {
            R firstTransferResult = bussinessTransferOrderService.transferOrder(firstTransferOrder, userInfo.getParentMerchantNo());
            if (firstTransferResult.isSuccess()) {
                BussinessUserWithdraw dbWithdraw = withDrawOrderResult.getData();
                dbWithdraw.setFailReason("受理成功，请等待结果");
                dbWithdraw.setReturnMsg(firstTransferResult.getMsg());
                this.withdrawService.updateById(dbWithdraw);
                if (firstTransferResult.getMsg().equals("REQUEST_RECEIVE")) {
                    this.handleFirstTransferScene(firstTransferOrder.getId());
                } else if (firstTransferResult.getMsg().equals("SUCCESS")) {
                    BussinessTransferOrder secondTransferOrder = new BussinessTransferOrder();
                    secondTransferOrder.setFromMerchantNo(firstTransferOrder.getToMerchantNo());
                    secondTransferOrder.setToMerchantNo(dbWithdraw.getMerchantNo());
                    secondTransferOrder.setTransferUsage("提现前转账到小微");
                    secondTransferOrder.setOrderAmount((dbWithdraw.getOrderAmount().add(new BigDecimal(withdrawRate))).toString());
                    secondTransferOrder.setFeeChargeSide("OUTSIDE");
                    secondTransferOrder.setRequestNo(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
                    secondTransferOrder.setTransferScene(SystemConstant.TransferScene.FOR_WITHDRAW_SECOND_TRANSFER.getValue());
                    secondTransferOrder.setTransferStatus(SystemConstant.TransferOrderStatus.WAIT.getValue());
                    this.bussinessTransferOrderService.save(secondTransferOrder);
                    dbWithdraw.setSecondTransferOrderId(secondTransferOrder.getId());
                    this.withdrawService.updateById(dbWithdraw);
                    R secondTransferResult = this.bussinessTransferOrderService.transferOrder(secondTransferOrder, firstTransferOrder.getToMerchantNo());
                    if (secondTransferResult.isSuccess()) {
                        if (secondTransferResult.getMsg().equals("REQUEST_RECEIVE")) {
                            this.handleSecondTransferScene(secondTransferOrder.getId());
                        } else if (secondTransferResult.getMsg().equals("SUCCESS")) {
                            this.withdrawOrder(dbWithdraw, userInfo.getParentMerchantNo());
                        }
                    } else {
                        dbWithdraw.setFailReason("代付失败");
                        dbWithdraw.setReturnMsg(secondTransferResult.getMsg());
                        this.withdrawService.updateById(dbWithdraw);
                        return R.fail("代付失败");
                    }
                }
                return R.success("受理成功，请等待结果");
            } else {
                return R.data(400, firstTransferOrder.getId(), firstTransferResult.getMsg());
            }
        } else {
            return R.fail("代付失败(CODE:YWSB)");
        }
    }

    private R<BussinessUserWithdraw> createWithDrawOrder(BussinessUserInfo userInfo, Long transferOrderId, String bussinessOrderId, Long userRegisterRequestId, BigDecimal withdrawAmount, String failReason, String returnMsg, String requestIp) {
        BussinessUserWithdraw withdraw = new BussinessUserWithdraw();
        withdraw.setUserInfoId(userInfo.getId());
        withdraw.setMerchantNo(userInfo.getMerchantNo());
        withdraw.setBankAccountNo(userInfo.getBankCardNo());
        withdraw.setFirstTransferOrderId(transferOrderId);
        withdraw.setOrderAmount(withdrawAmount);
        withdraw.setReceiveType("REAL_TIME");
        withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.WAIT.getValue());
        withdraw.setFailReason(failReason);
        withdraw.setReturnMsg(returnMsg);
        withdraw.setBussinessOrderId(bussinessOrderId);
        withdraw.setUserRegisterRequestId(userRegisterRequestId);
        withdraw.setRequestNo(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
        withdraw.setRequestIp(requestIp);
        withdraw.setReceiverAccountName(userInfo.getUserName());
        withdraw.setBankCode(userInfo.getBankCode());
        withdraw.setBussinessId(userInfo.getBussinessId());
        boolean save = this.withdrawService.save(withdraw);
        if (save) {
            return R.data(withdraw);
        } else {
            return R.fail("提现订单保存失败");
        }
    }

    /**
     * 创建小微用户进件申请和提现账单
     *
     * @param userInfo
     * @param excel
     * @return
     */
    private R userRegisterAndCreateWithdraw(BussinessUserInfo userInfo, WithdrawRequestExcel excel, String requestIp) {
        DecimalFormat debitDecimalFormat = new DecimalFormat("0.00");
        //先保存一个进件请求对象
        BussinessRegisterRequest bussinessRegisterRequest = new BussinessRegisterRequest();
        bussinessRegisterRequest.setUserInfoId(userInfo.getId());
        boolean requestSave = this.bussinessRegisterRequestService.save(bussinessRegisterRequest);
        if (requestSave) {
            R<BussinessUserWithdraw> result = this.createWithDrawOrder(userInfo, null, null, bussinessRegisterRequest.getId(), new BigDecimal(debitDecimalFormat.format(excel.getOrderAmount())), null, null, requestIp);
            if (result.isSuccess()) {
                R registerResult = this.bussinessRegisterRequestService.userRegister(bussinessRegisterRequest.getId(), userInfo.getId());
                if (registerResult.isSuccess()) {
                    return R.success("代付受理成功，请等待结果");
                } else {
                    BussinessUserWithdraw withdraw = result.getData();
                    withdraw.setWithdrawStatus(SystemConstant.WithdrawOrderStatus.FAIL.getValue());
                    withdraw.setFailReason(registerResult.getMsg());
                    withdraw.setReturnMsg(registerResult.getMsg());
                    this.withdrawService.updateById(withdraw);
                    return R.fail("代付失败(CODE:40000)");
                }
            } else {
                return R.fail("代付失败(CODE:40001)");
            }
        } else {
            return R.fail("代付失败(CODE:40002)");
        }
    }

    @Async
    public void importPayToUserList(List<WithdrawRequestExcel> withdrawRequestExcelList, Bussiness bussiness) {
        Bussiness parentBussiness = bussinessService.getById(bussiness.getParentBussinessId());
        for (WithdrawRequestExcel excel : withdrawRequestExcelList) {
            if (StringUtil.isBlank(excel.getBankCode())) {
                continue;
            }
            BussinessUserInfo userInfoDTO = this.toUserInfoFromImport(excel, bussiness.getId());
            userInfoDTO.setRateStrategyId(parentBussiness.getMicroRateStrategyId());
            userInfoDTO.setParentMerchantNo(parentBussiness.getMerchantNo());
            BussinessUserInfo dbUserInfo = userInfoService.getByNameCardBank(userInfoDTO);
            if (dbUserInfo == null) {
                boolean save = this.userInfoService.save(userInfoDTO);
                if (save) {
                    //情况一：发起小微用户进件和创建提现订单
                    this.userRegisterAndCreateWithdraw(userInfoDTO, excel, null);
                }
            } else {
                Integer registerStatus = dbUserInfo.getRegisterStatus();
                if (registerStatus != null && registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.SUCCESS.getValue()) {
                    //情况二：直接发起提现前第一次转账
                    this.transferOrderToPlatform(dbUserInfo, bussiness.getMerchantNo(), excel);
                } else if (registerStatus != null && (registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.SUBMIT_FAIL.getValue()
                        || registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.FAIL.getValue()
                        || registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.DOING.getValue())) {
                    {
                        userInfoDTO.setId(dbUserInfo.getId());
                        userInfoDTO.setCreateTime(dbUserInfo.getCreateTime());
                        BussinessUserInfo userInfo = BeanUtil.copyProperties(userInfoDTO, BussinessUserInfo.class);
                        boolean update = this.userInfoService.updateById(userInfo);
                        if (update) {
                            //情况三：同一个用户之前进件失败，修改了信息只有，现在重新发起一次代付，也是走情况一的录像
                            this.userRegisterAndCreateWithdraw(userInfoDTO, excel, null);
                        }
                    }
                }
            }
        }
    }

    @Async
    public R rePayToUser(Long withdrawId) {
        BussinessUserWithdraw withdraw = this.withdrawService.getById(withdrawId);
        org.springframework.util.Assert.notNull(withdraw, "账单记录不存在");
        Integer withdrawStatus = withdraw.getWithdrawStatus();
        if(withdrawStatus.intValue() == SystemConstant.WithdrawOrderStatus.SUCCESS.getValue()){
            return R.fail("交易已成功，请勿重复发起");
        }
        String withdrawFlag = withdraw.getWithdrawFlag();
        char[] chars = withdrawFlag.toCharArray();
        return R.status(false);
    }

    public R userSubmit(UserSubmitDto userSubmitDto){
        BladeUser bladeUser = AuthUtil.getUser();
        if(bladeUser == null){
            return R.data(400, "账号不存在");
        }
        Bussiness bussiness = bussinessService.getBaseMapper().selectOne(new QueryWrapper<>(new Bussiness()).lambda()
                .eq(Bussiness::getAccountId, bladeUser.getUserId()).eq(Bussiness::getSecret, userSubmitDto.getSecret()));
        if(bussiness == null){
            return R.data(400, "采购商不存在");
        }
        if(StringUtil.isBlank(userSubmitDto.getUserId())){
            //添加
            BussinessUserInfo newUserInfo = BeanUtil.copyProperties(userSubmitDto, BussinessUserInfo.class);
            if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.SETTLED_MERCHANT.getValue()){
                Bussiness parentBussiness = bussinessService.getById(bussiness.getParentBussinessId());
                newUserInfo.setParentMerchantNo(parentBussiness.getMerchantNo());
                newUserInfo.setRateStrategyId(parentBussiness.getMicroRateStrategyId());
            }else if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.PLATFORM_MERCHANT.getValue()){
                newUserInfo.setParentMerchantNo(bussiness.getMerchantNo());
                newUserInfo.setRateStrategyId(bussiness.getMicroRateStrategyId());
            }
            boolean save = this.userInfoService.save(newUserInfo);
            if(save){
                return R.fail("用户新增失败");
            }else{
                JSONObject data = new JSONObject();
                data.set("userId", newUserInfo.getId());
                return R.data(data, "用户新增成功");
            }
        }else {
            //更新
            Long userId = Func.toLong(userSubmitDto.getUserId());
            BussinessUserInfo dbUserInfo = this.userInfoService.getById(userId);
            if (dbUserInfo == null) {
                return R.fail("用户不存在");
            } else {
                Integer registerStatus = dbUserInfo.getRegisterStatus();
                if (registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.SUCCESS.getValue()
                        || registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.SUBMIT_SUCCESS.getValue()
                        || registerStatus.intValue() == SystemConstant.BussinessRegisterStatus.WAIT_AUDIT.getValue()) {
                    return R.fail("用户进件审核中，请勿修改");
                } else {
                    BussinessUserInfo updateUserInfo = BeanUtil.copyProperties(userSubmitDto, BussinessUserInfo.class);
                    updateUserInfo.setId(userId);
                    boolean update = this.userInfoService.updateById(updateUserInfo);
                    if (update) {
                        return R.fail("用户更新失败");
                    } else {
                        return R.success("用户更新成功");
                    }
                }
            }
        }
    }

    public R userRegister(UserRegisterDto userRegisterDto){
        BladeUser bladeUser = AuthUtil.getUser();
        if(bladeUser == null){
            return R.data(400, "FAIL", "账号不存在");
        }
        Bussiness bussiness = bussinessService.getBaseMapper().selectOne(new QueryWrapper<>(new Bussiness()).lambda()
                .eq(Bussiness::getAccountId, bladeUser.getUserId()).eq(Bussiness::getSecret, userRegisterDto.getSecret()));
        if(bussiness == null){
            return R.data(400, "FAIL", "采购商不存在");
        }
        BussinessUserInfo newUserInfo = BeanUtil.copyProperties(userRegisterDto, BussinessUserInfo.class);
        if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.SETTLED_MERCHANT.getValue()){
            Bussiness parentBussiness = bussinessService.getById(bussiness.getParentBussinessId());
            newUserInfo.setParentMerchantNo(parentBussiness.getMerchantNo());
            newUserInfo.setRateStrategyId(parentBussiness.getMicroRateStrategyId());
        }else if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.PLATFORM_MERCHANT.getValue()){
            newUserInfo.setParentMerchantNo(bussiness.getMerchantNo());
            newUserInfo.setRateStrategyId(bussiness.getMicroRateStrategyId());
        }
        newUserInfo.setBussinessId(bussiness.getId());
        newUserInfo.setRegisterStatus(SystemConstant.BussinessRegisterStatus.SUBMIT_SUCCESS.getValue());
        boolean save = this.userInfoService.save(newUserInfo);
        if(save){
            JSONObject data = new JSONObject();
            data.set("userId", newUserInfo.getId().toString());
            BussinessRegisterRequest registerRequest = new BussinessRegisterRequest();
            registerRequest.setUserInfoId(newUserInfo.getId());
            boolean requestSave = this.bussinessRegisterRequestService.save(registerRequest);
            if(requestSave){
                R registerResult = this.bussinessRegisterRequestService.userRegister(registerRequest.getId(), newUserInfo.getId());
                if(registerResult.isSuccess()){
                    data.set("status", "WAIT");
                    return R.data(data, "送审成功，请等待审核");
                }else{
                    return R.fail(registerResult.getMsg());
                }
            }else{
                data.set("status", "FAIL");
                return R.data(data, "业务进件请求保存失败");
            }
        }else{
            return R.fail("系统业务异常");
        }
    }

    public R userRegisterUpdate(UserRegisterDto userRegisterDto){
        BladeUser bladeUser = AuthUtil.getUser();
        Assert.notNull(bladeUser, "账号不存在");

        Bussiness bussiness = bussinessService.getBaseMapper().selectOne(new QueryWrapper<>(new Bussiness()).lambda()
                .eq(Bussiness::getAccountId, bladeUser.getUserId()).eq(Bussiness::getSecret, userRegisterDto.getSecret()));
        Assert.notNull(bussiness, "采购商不存在");
        String userId = userRegisterDto.getUserId();

        BussinessUserInfo userInfo = this.userInfoService.getById(userId);
        Assert.notNull(userInfo, "进件用户不存在，请发起新的进件");
        int registerStatus = userInfo.getRegisterStatus().intValue();
        if( registerStatus == SystemConstant.BussinessRegisterStatus.SUBMIT_SUCCESS.getValue()
            || registerStatus == SystemConstant.BussinessRegisterStatus.WAIT_AUDIT.getValue()
            || registerStatus == SystemConstant.BussinessRegisterStatus.SUCCESS.getValue()){
            return R.fail("用户" + userId + "进件中或已完成进件，请勿重新发起");
        }
        BussinessUserInfo updateUserInfo = BeanUtil.copyProperties(userRegisterDto, BussinessUserInfo.class);
        updateUserInfo.setId(Func.toLong(userRegisterDto.getUserId()));
        if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.SETTLED_MERCHANT.getValue()){
            Bussiness parentBussiness = bussinessService.getById(bussiness.getParentBussinessId());
            updateUserInfo.setParentMerchantNo(parentBussiness.getMerchantNo());
            updateUserInfo.setRateStrategyId(parentBussiness.getMicroRateStrategyId());
        }else if(bussiness.getBussinessType().intValue() == SystemConstant.BussinessType.PLATFORM_MERCHANT.getValue()){
            updateUserInfo.setParentMerchantNo(bussiness.getMerchantNo());
            updateUserInfo.setRateStrategyId(bussiness.getMicroRateStrategyId());
        }
        updateUserInfo.setBussinessId(bussiness.getId());
        updateUserInfo.setRegisterStatus(SystemConstant.BussinessRegisterStatus.SUBMIT_SUCCESS.getValue());
        boolean update = this.userInfoService.updateById(updateUserInfo);
        if(update){
            JSONObject data = new JSONObject();
            data.set("userId", updateUserInfo.getId().toString());
            BussinessRegisterRequest registerRequest = new BussinessRegisterRequest();
            registerRequest.setUserInfoId(updateUserInfo.getId());
            boolean requestSave = this.bussinessRegisterRequestService.save(registerRequest);
            if(requestSave){
                R registerResult = this.bussinessRegisterRequestService.userRegister(registerRequest.getId(), updateUserInfo.getId());
                if(registerResult.isSuccess()){
                    data.set("status", "WAIT");
                    return R.data(data, "送审成功，请等待审核");
                }else{
                    return R.fail(registerResult.getMsg());
                }
            }else{
                data.set("status", "FAIL");
                return R.data(data, "业务进件请求保存失败");
            }
        }else{
            return R.fail("系统业务异常");
        }
    }
}
