package cn.pluss.platform.merchant.impl.account;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.pluss.platform.BankCardService;
import cn.pluss.platform.IdCardService;
import cn.pluss.platform.channel.MerchantAuditService;
import cn.pluss.platform.common.AliyunService;
import cn.pluss.platform.constants.CommonError;
import cn.pluss.platform.converter.BankCardConverter;
import cn.pluss.platform.converter.Converter;
import cn.pluss.platform.dto.AccountDTO;
import cn.pluss.platform.dto.BankCardDTO;
import cn.pluss.platform.dto.BankInfoDTO;
import cn.pluss.platform.dto.CertificationDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.AccountMapper;
import cn.pluss.platform.mapper.BankCodeSxfMapper;
import cn.pluss.platform.mapper.RiskBlacklistMapper;
import cn.pluss.platform.merchant.AccountService;
import cn.pluss.platform.merchant.MerchantBaseInfoService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.merchantImage.MerchantImageService;
import cn.pluss.platform.notice.NoticeService;
import cn.pluss.platform.task.RyxMerAuditHandler;
import cn.pluss.platform.task.SxfMerAuditHandler;
import cn.pluss.platform.user.impl.GeneralPushUtil;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.vo.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Setter;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author Djh
 */
@Service("accountService")
@Primary
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {

    private static final int MAX_MIRCO_MERCHANT_NUM = 3;

    @Lazy
    @Autowired
    private UserAppService uaService;

    @Resource
    private BankCodeSxfMapper bankCodeSxfMapper;

    @Lazy
    @Autowired
    private IdCardService idCardService;

    @Lazy
    @Autowired
    private MerchantBaseInfoService mbiService;

    @Lazy
    @Autowired
    private MerchantImageService merchantImageService;

    @Lazy
    @Autowired
    private MerchantChannelStatusService mcsService;

    @Autowired
    private BankCardService bankCardService;

    @Autowired
    private MerchantImageService imgService;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private AliyunService aliyunService;

    @Resource
    private RiskBlacklistMapper riskBlacklistMapper;

    @Setter(onMethod_ = {@Autowired, @Qualifier("sxfMerchantAuditService")})
    private MerchantAuditService sxfMerchantAuditService;

    @Setter(onMethod_ = {@Autowired, @Qualifier("leshuaMerchantAuditService")})
    private MerchantAuditService leshuaMerchantAuditService;

    @Setter(onMethod_ = {@Autowired, @Qualifier("ryxMerchantAuditService")})
    private MerchantAuditService ryxMerchantAuditService;

    @Setter(onMethod_ = {@Autowired, @Qualifier("ysAuditServiceV2")})
    private MerchantAuditService ysAuditServiceV2;

    @Autowired @Lazy
    private RyxMerAuditHandler ryxMerAuditHandler;

    @Autowired
    private GeneralPushUtil generalPushUtil;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    @Lazy
    private SxfMerAuditHandler sxfMerAuditHandler;

    @Override
    public void editSuccess(MerchantChannelStatus mcs, String accountType) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByMerchantCode(mcs.getMerchantCode());
                Account account = getRealAccount(mbi.getUserId(), accountType);

                JSONObject bak = account.getBak();
                BankCard newBankCard = JSONObject.toJavaObject(bak, BankCard.class);
                newBankCard.setAccountType(BankCard.ACCOUNT_TYPE_PRIVATE);
                account.setBak(null);
                int count = count(new QueryWrapper<Account>().eq("bankCardId", account.getBankCardId()));
                if (count == 1) {
                    newBankCard.setId(Integer.parseInt(account.getBankCardId()));
                    bankCardService.updateById(newBankCard);
                } else {
                    bankCardService.save(newBankCard);
                    account.setBankCardId(newBankCard.getId() + "");
                }
                updateById(account);
                mcs.setStatus(MerchantChannelStatus.AUDIT_STATUS_SUCCESS);
                mcsService.updateById(mcs);

                String settleName = accountType.equals(Account.CHANNEL_TYPE_D1)? "次日到账": "实时到账";
                noticeService.sendEditApplySuccessNotice(mbi.getUserId() + "", mbi.getAlias(), settleName);
//                sxfMerAuditHandler.sendNotice(mbi.getUserId(), "结算账户修改通知", "结算账户修改成功", uniqueKey);
            }
        });
    }

    @Override
    public void editFail(MerchantChannelStatus mcs, String uniqueKey, String failReason, String accountType) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByMerchantCode(mcs.getMerchantCode());
                // 结算银行卡变更失败
                Account account = new Account().setUserId(mbi.getUserId()).setChannelType(accountType);
                account = getOne(new QueryWrapper<>(account));
                account.setBak(null);
                updateById(account);

                Notice notice = new Notice();
                notice.setUserId(mbi.getUserId());
                notice.setNoticeCode(UUID.randomUUID().toString().replace("-", ""));
                notice.setConrtent("D0-结算卡修改失败");
                noticeService.saveMerBankChangeNotice(notice);

                mcs.setStatus(MerchantChannelStatus.AUDIT_STATUS_SUCCESS);
                mcsService.updateById(mcs);

                sxfMerAuditHandler.sendNotice(mbi.getUserId(), "结算账户修改通知", "结算账户修改失败: " + failReason, uniqueKey);
            }
        });
    }

    @Override
    public Page<AccountVO> page(Page<Account> page, Account account, OrderItem orderItem) {
        if (orderItem == null) {
            orderItem = OrderItem.desc("createTime");
        }

        page.getOrders().clear();
        page.getOrders().add(orderItem);

        page = page(page, new QueryWrapper<>(account));

        Page<AccountVO> result = new Page<>();

        result.setTotal(page.getTotal());
        result.setSize(page.getSize());
        result.setPages(page.getPages());
        result.setCurrent(page.getCurrent());

        for (Account record : page.getRecords()) {
            // List<>
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(AccountDTO accountDTO) {
        accountDTO.paramCheck();

        bankCardService.checkBankInfo(accountDTO.getBankCard());

        IdCard accIdCard = accountDTO.getIdcard();
        if (accountDTO.getIdcard() != null) {
            // 没有身份证信息说明是法人进件
            accIdCard = idCardService.getLegalIdCard(accountDTO.getUserId());
        }

        // 原则上这里不需要再做空判断
        if (accIdCard != null) {
            RiskBlacklist riskBlacklist = new RiskBlacklist();
            riskBlacklist.setIdcardNo(accIdCard.getCertNo());
            Integer count = riskBlacklistMapper.selectCount(Wrappers.query(riskBlacklist));
            if (count > 0) {
                throw new MsgException("当前结算人已在风控黑名单中，请更换结算信息");
            }
        }

        // 判断是否已经进件
        UserApp userApp = new UserApp().setUserId(Long.parseLong(accountDTO.getUserId()));
        userApp = uaService.queryUserApp(userApp);

        MerchantChannelStatus merchantChannelStatus = new MerchantChannelStatus();
        merchantChannelStatus.setMerchantCode(userApp.getMerchantCode());
        QueryWrapper<MerchantChannelStatus> qWrapper = new QueryWrapper<>(merchantChannelStatus).orderByAsc("createTime").last("limit 1");
        qWrapper.in("virChannelFlag", merchantChannelStatus.getVirChannelFlag(), "1");
        merchantChannelStatus = mcsService.getOne(qWrapper);

        if (merchantChannelStatus == null) {
            saveV4(accountDTO);
            return;
        }

        // 进件通过/进件审核/商户信息变更时，不允许再用此接口变更结算信息
        if (MerchantChannelStatus.isAudited(merchantChannelStatus)) {
            throw new MsgException("当前商户状态不允许提交结算信息");
        } else {
            saveV4(accountDTO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveV4(AccountDTO accountDTO, boolean checkFlag) {
        MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByUserId(accountDTO.getUserId());
        if (StringUtils.isEmpty(accountDTO.getChannelType())) {
            MerchantChannelStatus mcsD1 = mcsService.getByMerchantCodeAndChannelType(mbi.getMerchantCode(), Account.CHANNEL_TYPE_D1);
            mcsD1 = Optional.ofNullable(mcsD1).orElse(new MerchantChannelStatus());
            if (Objects.equals(mcsD1.getStatus(), MerchantChannelStatus.AUDIT_STATUS_SUCCESS)
                || Objects.equals(mcsD1.getStatus(), MerchantChannelStatus.AUDIT_STATUS_EXAMINING)
                || Objects.equals(mcsD1.getStatus(), MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT)) {
                accountDTO.setChannelType(Account.CHANNEL_TYPE_D0);
            } else {
                accountDTO.setChannelType(Account.CHANNEL_TYPE_D1);
            }
        }

        if (checkFlag) {
            MerchantChannelStatus mcs = mcsService.getByMerchantCodeAndChannelType(mbi.getMerchantCode(), accountDTO.getSettleType());
            mcs = Optional.ofNullable(mcs).orElse(new MerchantChannelStatus());
            if (Objects.equals(mcs.getStatus(), MerchantChannelStatus.AUDIT_STATUS_SUCCESS)
                    || Objects.equals(mcs.getStatus(), MerchantChannelStatus.AUDIT_STATUS_EXAMINING)
                    || Objects.equals(mcs.getStatus(), MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT)) {
                throw new MsgException("当前状态不允许修改结算卡信息");
            }
        }

        List<String> channelTypeList = new ArrayList<>();
        channelTypeList.add(Account.CHANNEL_TYPE_D0);
        channelTypeList.add(Account.CHANNEL_TYPE_D1);

        if (!channelTypeList.contains(accountDTO.getChannelType())) {
            throw new MsgException("通道类型错误");
        }

        if (Account.SETTLE_TYPE_PRIVATE_ILLEGAL.equals(accountDTO.getSettleType())) {
            MsgException.checkNull(accountDTO.getIdcard(), CommonError.NO_ACC_ID_CARD_INFO);
        } else {
            // 小微，如果未传身份证信息，则获取对私身份信息
            if (accountDTO.getIdcard() == null && Account.SETTLE_TYPE_MICRO_STORE.equals(accountDTO.getSettleType())) {
                Account account = new Account();
                account.setChannelType(accountDTO.getChannelType()).setUserId(accountDTO.getUserId());
                account = getOne(new QueryWrapper<>(account));

                if (account != null) {
                    IdCard accIdCard = idCardService.getById(account.getIdCardId());
                    MsgException.checkNull(accIdCard, "缺少结算人身份信息");
                    accountDTO.setIdcard(accIdCard);
                } else {
                    LambdaQueryWrapper<IdCard> idCardQueryWrapper = Wrappers.lambdaQuery();
                    idCardQueryWrapper.eq(IdCard::getUserId, accountDTO.getUserId())
                            .eq(IdCard::getUserType, IdCard.TYPE_ACCOUNT);
                    IdCard accIdCard = idCardService.getOne(idCardQueryWrapper);
                    MsgException.checkNull(accIdCard, "缺少结算人身份信息");
                    accountDTO.setIdcard(accIdCard);
                }
            }
        }

        accountDTO.paramCheck();

        bankCardService.checkBankInfo(accountDTO.getBankCard());

        IdCard accIdCard = Optional.ofNullable(accountDTO.getIdcard()).orElseGet(() -> {
            // 没有身份证信息说明是法人进件
            return idCardService.getLegalIdCard(accountDTO.getUserId());
        });

        // 原则上这里不需要再做空判断
        if (accIdCard != null) {
            RiskBlacklist riskBlacklist = new RiskBlacklist();
            riskBlacklist.setIdcardNo(accIdCard.getCertNo());
            Integer count = riskBlacklistMapper.selectCount(Wrappers.query(riskBlacklist));
            if (count > 0) {
                throw new MsgException("当前结算人已在风控黑名单中，请更换结算信息");
            }
        }

        delAccount(accountDTO.getUserId(), accountDTO.getChannelType());

        Account account = Converter.INSTANCE.toEntity(accountDTO);

        if (Account.SETTLE_TYPE_CORPORATE.equals(accountDTO.getSettleType())) {
            IdCard legalIdCard = idCardService.getLegalIdCard(account.getUserId());
            MsgException.checkNull(legalIdCard, CommonError.NO_LEGAL_ID_CARD_INFO);
            accountDTO.setIdcard(legalIdCard);
            account.setIdCardId(legalIdCard.getId() + "");
            accountDTO.getBankCard().setBankHolder(mbi.getBussAuthName());
        } else if (accountDTO.getSettleType().startsWith(Account.SETTLE_TYPE_PRIVATE_LEGAL)) {
            IdCard legalIdCard = idCardService.getLegalIdCard(account.getUserId());
            if (legalIdCard == null) {
                throw new MsgException(CommonError.NO_LEGAL_ID_CARD_INFO);
            }

            if (accIdCard == null) {
                accIdCard = legalIdCard;
                idCardService.save(accIdCard);
            } else {
                accIdCard.setId(legalIdCard.getId());
                idCardService.updateById(accIdCard);
            }
            account.setIdCardId(accIdCard.getId() + "");
            accountDTO.setIdcard(accIdCard);
            accountDTO.getBankCard().setBankHolder(accIdCard.getCertName());
        } else {
            idCardService.save(accountDTO.getIdcard());
            accountDTO.getBankCard().setBankHolder(accountDTO.getIdcard().getCertName());
            account.setIdCardId(accountDTO.getIdcard().getId() + "");
        }

        IdCard certIdCard = idCardService.getCertIdCard(accountDTO.getUserId());

        if (mbi.getMerchantType().equals(MerchantBaseInfo.MERCH_TYPE_MICRO)) {
            // 小微需要结算人与实名人是同一个人
            IdCard idcard = accountDTO.getIdcard();
            if (idcard != null) {
                if (!idcard.getCertNo().equals(certIdCard.getCertNo())) {
                    throw new MsgException("小微商户结算人必须是自己");
                }
            }
        }

        boolean settleTypeFlag = Account.SETTLE_TYPE_CORPORATE.equals(accountDTO.getSettleType());
        //TODO 测试时先注掉
        if (checkFlag && !(settleTypeFlag)) {
            // 执行银行卡四要素校验
            aliyunService.checkBankCorrectNow(accountDTO.getBankCard().getPhone(), accountDTO.getBankCard().getBankCardNo()
                    , accountDTO.getIdcard().getCertNo()
                    , accountDTO.getBankCard().getBankHolder(), "结算人与结算银行卡不匹配，请核对结算信息");
        }

        bankCardService.save(accountDTO.getBankCard());
        account.setBankCardId(accountDTO.getBankCard().getId() + "");
        save(account);

        if (!accountDTO.getChannelType().equals(Account.CHANNEL_TYPE_D1)) {
            return;
        }

        // 如果不存在D0的结算信息，则直接将D1的结算信息带过来
        LambdaQueryWrapper<Account> qWrapperAccountD1 = Wrappers.lambdaQuery();
        qWrapperAccountD1.eq(Account::getUserId, accountDTO.getUserId()).eq(Account::getChannelType, Account.CHANNEL_TYPE_D0);
        int count = baseMapper.selectCount(qWrapperAccountD1);
        if (count == 0) {
            account.setChannelType(Account.CHANNEL_TYPE_D0);
            save(account);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void realNameAudit(CertificationDTO certificationDTO) {
        UserApp tokenUa = uaService.queryUserAppByToken();
        if ("agent".equals(tokenUa.getUserType()) && "ZY_BST".equals(tokenUa.getRoleCode())) {
            IdCard condition = new IdCard().setCertNo(certificationDTO.getCertnum());
            List<IdCard> idCardList = idCardService.list(new QueryWrapper<>(condition).select(" DISTINCT userId"));
            for (IdCard idCard : idCardList) {
                UserApp userApp = uaService.getUserAppByUserId(idCard.getUserId());
                userApp.setSpreadFlag("0");
                uaService.updateById(userApp);
            }
        }

        // 查询当前用户是否存在
        UserApp userApp = new UserApp();
        userApp.setUserId(Long.valueOf(certificationDTO.getUserId()));
        List<UserApp> queryUserAppList = uaService.queryUserAppList(userApp);
        if (queryUserAppList == null || queryUserAppList.isEmpty()) {
            throw new MsgException("查无此人！");
        } else {
            userApp = queryUserAppList.get(0);
            // 暂不修改用户名称，完成银行卡实名认证之后，再将姓名填充进去
        }

        certificationDTO.paramCheck();
        // 保存userApp数据
        if (StringUtils.isEmpty(userApp.getMerchantCode())) {
            String merchantCode = "M800" + DateUtil.format(new Date(), "yyyyMMdd") + StringUtil.random6V2();
            userApp.setMerchantCode(merchantCode);
            uaService.updateById(userApp);
        }

        if (Objects.equals(userApp.getStatus(), 1) || Objects.equals(userApp.getStatus(), 3)) {
            throw new MsgException("当前状态不允许修改实名认证信息");
        }

        // 保存身份证信息
        IdCard idCard = new IdCard();
        idCard.setUserId(certificationDTO.getUserId());
        idCard.setCertType("00");
        idCard.setUserType(IdCard.TYPE_CERT);
        IdCard existIdCard = idCardService.getOne(new QueryWrapper<>(idCard));
        if (existIdCard != null) {
            idCard.setId(existIdCard.getId());
        }

        idCard.setCertName(certificationDTO.getRealName());
        idCard.setCertNo(certificationDTO.getCertnum());
        idCard.setCertStartTime(certificationDTO.getCertStartTime());
        idCard.setCertEndTime(certificationDTO.getCertPeriod());
        idCard.setCertType("00");
        idCard.setUserType(IdCard.TYPE_CERT);
        idCard.setUserId(certificationDTO.getUserId());
        idCard.setImgPositive(certificationDTO.getCertFullPhoto());
        idCard.setImgNegative(certificationDTO.getCertBacKPhoto());
        idCardService.saveOrUpdate(idCard);

        userApp.setStatus(1);
        uaService.updateById(userApp);
    }

    @Override
    public IdCardVO idCardDetail(String userId) {
        IdCard legalIdCard = idCardService.getCertIdCard(userId);

        IdCardVO idCardVO = new IdCardVO();
        idCardVO.setCertBacKPhoto(legalIdCard.getImgNegative());
        idCardVO.setCertFullPhoto(legalIdCard.getImgPositive());
        idCardVO.setCertnum(legalIdCard.getCertNo());
        idCardVO.setCertStartTime(legalIdCard.getCertStartTime());
        idCardVO.setCertPeriod(legalIdCard.getCertEndTime());
        idCardVO.setRealName(legalIdCard.getCertName());
        return idCardVO;
    }

    @Override
    public void checkCert(String certNo, String checkMsg) {
        Integer num = 0;
        try {
            num = baseMapper.selectMicroMbiAccountNum(certNo);
        } catch (Exception e) {
            log.error(e.toString());
        }

        if (num >= MAX_MIRCO_MERCHANT_NUM) {
            throw new MsgException(checkMsg);
        }
    }

    @Override
    public StoreSummaryVO getReckoner(String userId, String merchantType) {
        StoreSummaryVO storeSummaryVO = new StoreSummaryVO();
        // 获取店铺基本信息
        MerchantBaseInfo mbi = getMerchantBaseInfo(userId);

        // 是否存在同商户类型的数据
        boolean hasSameMerType = mbi != null && merchantType.equals(mbi.getMerchantType());

        boolean hasRejectData = "-1".equals(merchantType) && mbi != null;
        if (hasSameMerType || hasRejectData) {
            inputExistData(storeSummaryVO, mbi);
        }

        inputMerchantStatus(storeSummaryVO, mbi);

        return storeSummaryVO;
    }

    @Override
    public StoreSummaryVO getReckonerV2(String userId, String merchantType) {
        // 获取店铺基本信息
        StoreSummaryVO storeSummaryVO = new StoreSummaryVO();
        // 获取店铺基本信息
        MerchantBaseInfo mbi = getMerchantBaseInfo(userId);

        // 是否存在同商户类型的数据
        boolean hasSameMerType = mbi != null && merchantType.equals(mbi.getMerchantType());

        boolean hasRejectData = "-1".equals(merchantType) && mbi != null;
        if (hasSameMerType || hasRejectData) {
            storeSummaryVO.setMerchantBaseInfo(mbi);
            if (!"1".equals(mbi.getMerchantType())) {
                IdCard legalIdCard = idCardService.getLegalIdCard(userId);
                if (legalIdCard != null) {
                    storeSummaryVO.setLegalPersonInfo(legalIdCard);
                }

                BusinessLicenseVO businessLicense = getBusinessLicense(mbi);
                storeSummaryVO.setBusinessLicense(businessLicense);
            }

            MerchantImage merchantImage = new MerchantImage(mbi.getMerchantCode(), MerchantImage.ImageType.CASH_DESK_WITH_PERSON);
            merchantImage = merchantImageService.getOne(new QueryWrapper<>(merchantImage));
            storeSummaryVO.setCertInfoStatus(merchantImage == null ? StoreSummaryVO.NO_DATA : StoreSummaryVO.HAS_DATA);

            AccountDTO d1 = getRealAccount(userId, Account.CHANNEL_TYPE_D1);
            storeSummaryVO.setD1(d1);
            AccountDTO d0 = getRealAccount(userId, Account.CHANNEL_TYPE_D0);
            storeSummaryVO.setD0(d0);
            
            MerchantChannelStatus mcsCurrent = mcsService.getValidData(mbi.getMerchantCode());
            if (mcsCurrent == null || mcsCurrent.getVirChannelFlag().equals(Account.CHANNEL_TYPE_D1)) {
                if (d1 != null) {
                    storeSummaryVO.setSettleType(d1.getSettleType());
                }
            } else {
                if (d0 != null) {
                    storeSummaryVO.setSettleType(d0.getSettleType());
                }
            }
        }

        inputMerchantStatus(storeSummaryVO, mbi);

        return storeSummaryVO;
    }

    private void inputMerchantStatus(StoreSummaryVO storeSummaryVO, MerchantBaseInfo mbi) {
        if (mbi == null) {
            return;
        }

        MerchantChannelStatus mcs = mcsService.getValidData(mbi.getMerchantCode());

        if (mcs != null && MerchantChannelStatus.AUDIT_STATUS_WAITING_SIGN.equals(mcs.getStatus())) {
            switch (mcs.getChannel()) {
                case 1:
                    break;
                case 3:
                    // 拼接成真正的orderId
                    String applicationId = mcs.getApplicationId();
                    String orderId = applicationId.substring(0, 8) + "-" +
                            applicationId.substring(8, 12) + "-" +
                            applicationId.substring(12, 16) + "-" +
                            applicationId.substring(16, 20) + "-" +
                            applicationId.substring(20);

                    Map<String, Object> param = new HashMap<>();
                    param.put("orderId", orderId);
                    try {
                        JSONObject jsonObject = ryxMerchantAuditService.merchantAuditResult(param);
                        ryxMerAuditHandler.auditCallback(jsonObject);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    break;
                case 4:
                    try {
                        JSONObject params = new JSONObject();
                        if (mcs.getApplicationId() == null) {
                            break;
                        }
                        params.put("sysFlowId", mcs.getApplicationId());
                        ysAuditServiceV2.merchantAuditResult(params);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    break;
            }

            mcs = mcsService.getValidData(mbi.getMerchantCode());
        }

        String merchantAuditStatus;
        if (mcs == null) {
            merchantAuditStatus = "0";
            storeSummaryVO.setMerchantAuditStatus(merchantAuditStatus);
            return;
        }

        merchantAuditStatus = mcs.getAppStatus();
        storeSummaryVO.setMerchantAuditStatus(merchantAuditStatus);
        String auditReason = mcs.getRemark();
        storeSummaryVO.setAuditReason(auditReason);

        if (MerchantChannelStatus.AUDIT_STATUS_WAITING_SIGN.equals(mcs.getStatus())) {
            storeSummaryVO.setSignStatus("0");
            String signUrl = getSignUrl(mbi, mcs);
            storeSummaryVO.setSignUrl(signUrl);
            storeSummaryVO.setAuditReason("签约状态会在签约完成后5分钟内刷新");
        } else if (MerchantChannelStatus.AUDIT_STATUS_SIGNED.equals(mcs.getStatus())) {
            storeSummaryVO.setSignStatus("1");
        } else {
            storeSummaryVO.setSignStatus("-1");
        }

        if (MerchantChannelStatus.AUDIT_STATUS_EXAMINING.equals(mcs.getStatus()) && "5".equals(mcs.getThirdStatus())) {
            storeSummaryVO.setSignStatus("0");
            String signUrl = getSignUrl(mbi, mcs);
            storeSummaryVO.setSignUrl(signUrl);
            storeSummaryVO.setAuditReason("签约状态会在签约完成后5分钟内刷新");
        }

        storeSummaryVO.setMerchantAuditStatus(merchantAuditStatus);
    }

    private String getSignUrl(MerchantBaseInfo mbi, MerchantChannelStatus mcs) {
        String merName;

        if (mcs.getChannel() == 3) {
            if ("1".equals(mbi.getMerchantType())) {
                AccountDTO account = getRealAccount(mbi.getUserId());
                merName = "商户" + account.getIdcard().getCertName();
            } else {
                merName = mbi.getBussAuthName();
            }

            try {
                merName = URLEncoder.encode(merName, "UTF-8");
            } catch (UnsupportedEncodingException ignored) {
                // ignored
            }

            String urlTemplate = "https://rjp.ruiyinxin.com/mims2/ruijiaSign/index.html?merInId=%s&merName=%s";

            return String.format(urlTemplate, mcs.getExtra().getString("merInId"), merName);
        }

        if (mcs.getChannel() == 4) {
            return mcs.getExtra().getString("signUrl");
        }

        return null;
    }

    /**
     * 获取现有结算数据
     *
     * @param storeSummaryVO 结果实体类
     * @param existData      商户信息
     */
    private void inputExistData(StoreSummaryVO storeSummaryVO, MerchantBaseInfo existData) {

        storeSummaryVO.setMerchantBaseInfo(existData);
        storeSummaryVO.setMerchantBaseInfoStatus(StoreSummaryVO.HAS_DATA);

        if ("1".equals(existData.getMerchantType())) {
            inputMicroExistData(storeSummaryVO, existData);
        } else {
            inputMerchantExistData(storeSummaryVO, existData);
        }

        MerchantImage merchantImage = new MerchantImage(existData.getMerchantCode(), MerchantImage.ImageType.CASH_DESK_WITH_PERSON);
        merchantImage = merchantImageService.getOne(new QueryWrapper<>(merchantImage));
        storeSummaryVO.setCertInfoStatus(merchantImage == null ? StoreSummaryVO.NO_DATA : StoreSummaryVO.HAS_DATA);
    }

    /**
     * 拼装小微商户的结算信息
     */
    private void inputMicroExistData(StoreSummaryVO storeSummaryVO, MerchantBaseInfo existData) {
        MerchantChannelStatus mcs = mcsService.getValidData(existData.getMerchantCode());
        Account account = new Account().setUserId(existData.getUserId());
        if (mcs != null && Objects.equals(mcs.getChannel(), 4)) {
            account.setChannelType(Account.CHANNEL_TYPE_D0);
        } else {
            account.setChannelType(Account.CHANNEL_TYPE_D1);
        }

        account = getOne(new QueryWrapper<>(account));

        if (account != null && !account.getSettleType().equals(Account.SETTLE_TYPE_MICRO_STORE)) {
            return;
        }
        
        AccountDTO realAccount;
        if (account != null) {
            realAccount = Converter.INSTANCE.toDTO(account);
            IdCard idCard = idCardService.getById(account.getIdCardId());
            realAccount.setIdcard(idCard);
            BankCard bankCard = bankCardService.getById(account.getBankCardId());
            realAccount.setBankCard(bankCard);
        } else {
            realAccount = new AccountDTO();
            LambdaQueryWrapper<IdCard> qWrapper = Wrappers.lambdaQuery();
            qWrapper.eq(IdCard::getUserId, existData.getUserId()).eq(IdCard::getUserType, IdCard.TYPE_ACCOUNT);
            IdCard idCard = idCardService.getOne(qWrapper);
            realAccount.setIdcard(idCard);
        }

        storeSummaryVO.setReckonerInfo(realAccount.getIdcard());
        storeSummaryVO.setReckonerBankInfo(realAccount.getBankCard());
        storeSummaryVO.setSettleType(realAccount.getSettleType());
    }

    /**
     * 拼装个体/企业商户的结算信息和法人信息
     */
    private void inputMerchantExistData(StoreSummaryVO storeSummaryVO, MerchantBaseInfo existData) {
        BusinessLicenseVO businessLicense = getBusinessLicense(existData);
        if (businessLicense != null) {
            storeSummaryVO.setBusinessLicenseStatus(StoreSummaryVO.HAS_DATA);
            storeSummaryVO.setBusinessLicense(businessLicense);
        } else {
            storeSummaryVO.setBusinessLicenseStatus(StoreSummaryVO.NO_DATA);
            // 个体/企业商户，没有营业执照就不存在法人和结算信息
            return;
        }

        AccountDTO realAccount = getRealAccount(existData.getUserId());

        if (realAccount != null && !realAccount.getSettleType().equals(Account.SETTLE_TYPE_MICRO_STORE)) {
            storeSummaryVO.setReckonerInfo(realAccount.getIdcard());
            storeSummaryVO.setReckonerInfoStatus(StoreSummaryVO.HAS_DATA);
            storeSummaryVO.setReckonerBankInfo(realAccount.getBankCard());
            storeSummaryVO.setReckonerBankInfoStatus(StoreSummaryVO.HAS_DATA);
            storeSummaryVO.setSettleType(realAccount.getSettleType());
        }

        IdCard legalIdCard = idCardService.getLegalIdCard(existData.getUserId());
        if (legalIdCard != null) {
            storeSummaryVO.setLegalPersonInfo(legalIdCard);
            storeSummaryVO.setLegalPersonInfoStatus(StoreSummaryVO.HAS_DATA);
        }
    }

    /**
     * 获取经营信息/店铺基本信息
     */
    private MerchantBaseInfo getMerchantBaseInfo(String userId) {
        QueryWrapper<MerchantBaseInfo> merchantBaseInfoQueryWrapper = new QueryWrapper<MerchantBaseInfo>().eq("userId", userId);
        MerchantBaseInfo mbi = mbiService.getOne(merchantBaseInfoQueryWrapper);

        if (mbi == null) {
            return null;
        }

        //获取图片信息
        MerchantImage merchantImage = new MerchantImage();
        merchantImage.setMerchantCode(mbi.getMerchantCode());
        List<MerchantImage> imageList = merchantImageService.queryMerchantImageList(merchantImage);

        for (MerchantImage item : imageList) {
            MerchantBaseInfo.cpImgUrl(mbi, item);
        }

        return mbi;
    }

    @Override
    public boolean saveOrUpdate(Account entity) {
        if (entity.getUserId() != null) {
            Account exist = new Account().setUserId(entity.getUserId()).setChannelType(Account.CHANNEL_TYPE_D1);
            exist = getOne(new QueryWrapper<>(exist));

            if (exist != null) {
                entity.setId(exist.getId());
            }
        }

        if (entity.getId() != null) {
            updateById(entity);
            // 没有D0信息就创建
            Account accountD0 = getRealAccount(entity.getUserId(), Account.CHANNEL_TYPE_D0);
            if (accountD0 == null) {
                entity.setChannelType(Account.CHANNEL_TYPE_D0);
                save(entity);
            } else {
                entity.setId(accountD0.getId());
                updateById(entity);
            }
        } else {
            save(entity);
            // 没有D0信息就创建
            Account accountD0 = getRealAccount(entity.getUserId(), Account.CHANNEL_TYPE_D0);
            if (accountD0 == null) {
                entity.setChannelType(Account.CHANNEL_TYPE_D0);
                save(entity);
            }
        }

        return super.saveOrUpdate(entity);
    }

    /**
     * 保存图片数据
     *
     * @param merchantCode     商户code
     * @param bankCard         银行卡信息
     * @param legalIdCard      法人/商户负责人身份证信息
     * @param accountIdcIdCard 结算人身份证信息
     * @param certificateUrl   非法人授权函
     */
    @Override
    public void saveImage(String merchantCode, BankCard bankCard, IdCard legalIdCard, IdCard accountIdcIdCard, String certificateUrl) {
        // 法人身份证正面
        imgService.saveMerchantImageUpload(merchantCode, legalIdCard.getImgPositive(), MerchantImage.ImageType.IDCARD_FRONT);
        // 法人身份证反面
        imgService.saveMerchantImageUpload(merchantCode, legalIdCard.getImgNegative(), MerchantImage.ImageType.IDCARD_BACK);

        // 对公结算不需要传结算身份信息
        if (accountIdcIdCard == null) {
            imgService.saveMerchantImageUpload(merchantCode, bankCard.getLicenseUrl(), MerchantImage.ImageType.ACCOUNT_PERMITS);
            return;
        }

        // 银行卡正面
        imgService.saveMerchantImageUpload(merchantCode, bankCard.getImgUrl(), MerchantImage.ImageType.BANK_CARD_FRONT);

        // 结算人身份证正面
        imgService.saveMerchantImageUpload(merchantCode, accountIdcIdCard.getImgPositive(), MerchantImage.ImageType.SETTLE_IDCARD_FRONT);
        // 结算人身份证反面
        imgService.saveMerchantImageUpload(merchantCode, accountIdcIdCard.getImgNegative(), MerchantImage.ImageType.SETTLE_IDCARD_BACK);

        // 非法人结算的话，需要非法人授权函
        if (!accountIdcIdCard.getCertNo().equals(legalIdCard.getCertNo())) {
            imgService.saveMerchantImageUpload(merchantCode, certificateUrl, MerchantImage.ImageType.NON_LEG_SETTLE_AUTH);
        }
    }

    private BusinessLicenseVO getBusinessLicense(MerchantBaseInfo existData) {
        boolean hasBusinessLicense = StringUtils.isNotEmpty(existData.getPrincipalPerson());

        if (!hasBusinessLicense) {
            return null;
        }

        // 组装营业执照信息
        BusinessLicenseVO businessLicenseVO = new BusinessLicenseVO();
        businessLicenseVO.setPrincipalPerson(existData.getPrincipalPerson());
        businessLicenseVO.setBusinessLicensePic(existData.getBusinessLicensePic());
        businessLicenseVO.setBussAuthName(existData.getBussAuthName());
        businessLicenseVO.setBussAuthNum(existData.getBussAuthNum());
        businessLicenseVO.setBussAuthAddress(existData.getBussAuthAddress());
        businessLicenseVO.setBussAuthStartTime(existData.getBussAuthStartTime());
        String bussAuthEndTime = existData.getBussAuthEndTime();
        businessLicenseVO.setBussAuthEndTime(bussAuthEndTime);

        boolean isLongAuthTime = bussAuthEndTime != null && (bussAuthEndTime.startsWith("2099") || bussAuthEndTime.startsWith("2999"));
        // 判断长期
        if (isLongAuthTime) {
            businessLicenseVO.setTypeCode("1");
            businessLicenseVO.setTypeDesc("长期");
        } else {
            businessLicenseVO.setTypeCode("0");
            businessLicenseVO.setTypeDesc("短期");
        }

        return businessLicenseVO;
    }

    @Override
    public BankCardVO bankcardDetail(String userId) {
        QueryWrapper<BankCard> bankCardQueryWrapper = new QueryWrapper<>();
        bankCardQueryWrapper.eq("userId", userId);
        bankCardQueryWrapper.eq("accountType", BankCard.ACCOUNT_TYPE_CERT);
        BankCard bankCard = bankCardService.getOne(bankCardQueryWrapper);

        if (bankCard == null) {
            throw new MsgException("暂无银行卡信息");
        }

        BankCardVO bankCardVO = new BankCardVO();
        bankCardVO.setAccountType(bankCard.getAccountType());
        bankCardVO.setBranchProvince(bankCard.getBranchProvince());
        bankCardVO.setBranchCity(bankCard.getBranchCity());
        bankCardVO.setBranchArea(bankCard.getBranchArea());
        bankCardVO.setBankAddress(bankCard.getBranchProvince() + "," + bankCard.getBranchCity() + "," + bankCard.getBranchArea());
        bankCardVO.setBankAddressNo(bankCard.getBankAddressNo());
        bankCardVO.setBankCardFrontPic(bankCard.getImgUrl());
        bankCardVO.setBankCardNo(bankCard.getBankCardNo());
        bankCardVO.setBankName(bankCard.getBankName());
        bankCardVO.setContactLine(bankCard.getContactLine());
        bankCardVO.setPhone(bankCard.getPhone());
        bankCardVO.setBranchName(bankCard.getBranchName());

        return bankCardVO;
    }

    @Override
    public AccountDTO getAccount(String userId) {
        MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByUserId(userId);
        if (mbi == null) {
            return getRealAccount(userId, Account.CHANNEL_TYPE_D1);
        }

        MerchantChannelStatus mcs = mcsService.getValidData(mbi.getMerchantCode());
        if (mcs == null || !Objects.equals(mcs.getChannel(), 4)) {
            return getRealAccount(userId, Account.CHANNEL_TYPE_D1);
        } else {
            return getRealAccount(userId, Account.CHANNEL_TYPE_D0);
        }
    }

    @Override
    public Map<String, AccountDTO> getAccounts(String userId) {
        AccountDTO accountD1 = getRealAccount(userId, Account.CHANNEL_TYPE_D1);
        AccountDTO accountD0 = getRealAccount(userId, Account.CHANNEL_TYPE_D0);

        Map<String, AccountDTO> result = new HashMap<>();
        if (accountD1 != null && accountD1.getIdcard() != null) {
            result.put(Account.CHANNEL_TYPE_D1, accountD1);
        }

        if (accountD0 != null && accountD0.getIdcard() != null) {
            result.put(Account.CHANNEL_TYPE_D0, accountD0);
        }

        return result;
    }

    @Override
    public AccountDTO getRealAccount(Account account) {
        String userId = account.getUserId();
        if (account.getChannelType() == null) {
            throw new MsgException("缺少结算通道类型");
        }

        List<String> bloomFilter = new ArrayList<>(2);
        bloomFilter.add(Account.CHANNEL_TYPE_D0);
        bloomFilter.add(Account.CHANNEL_TYPE_D1);
        if (!bloomFilter.contains(account.getChannelType())) {
            throw new MsgException("未知的结算类型");
        }

        account = getOne(new QueryWrapper<>(account));
        AccountDTO accountDTO = Converter.INSTANCE.toDTO(account);
        MerchantBaseInfo mbi = new MerchantBaseInfo().setUserId(userId);
        mbi = mbiService.queryMerchantBaseInfo(mbi);

        if (mbi == null) {
            return null;
        }

        // 用户不存在结算信息
        String merchantType = mbi.getMerchantType();

        if (account == null && "1".equals(merchantType)) {
            AccountDTO result = new AccountDTO();
            result.setUserId(mbi.getUserId()).setSettleType(Account.SETTLE_TYPE_MICRO_STORE);
            return result;
        }

        // 异或，小微但结算信息不是小微，非小微但结算信息是小微
        if (account == null || "1".equals(merchantType) ^ account.getSettleType().equals(Account.SETTLE_TYPE_MICRO_STORE)) {
            return null;
        }

        // 获取身份证信息
        IdCard idCard = idCardService.getById(account.getIdCardId());
        accountDTO.setIdcard(idCard);

        // 获取银行卡信息
        BankCard bankCard = bankCardService.getById(account.getBankCardId());
        accountDTO.setBankCard(bankCard);

        if (account.getSettleType() == null) {
            throw new MsgException("未知结算类型");
        }

        Optional.ofNullable(account.getSettleType()).ifPresent(s -> {
            if (s.startsWith(Account.SETTLE_TYPE_PRIVATE_ILLEGAL)) {
                UserApp userApp = new UserApp().setUserId(Long.parseLong(userId));
                userApp = uaService.queryUserApp(userApp);

                MerchantImage merchantImage = new MerchantImage()
                        .setMerchantCode(userApp.getMerchantCode())
                        .setPhotoType(MerchantImage.ImageType.NON_LEG_SETTLE_AUTH);

                merchantImage = merchantImageService.queryMerchantImage(merchantImage);
                Optional.ofNullable(merchantImage).ifPresent(v -> accountDTO.setCertificateUrl(v.getPicUrl()));
            }
        });


        MerchantChannelStatus mcs = mcsService.getByMerchantCodeAndChannelType(mbi.getMerchantCode(), account.getChannelType());
        if (mcs == null || !MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT.equals(mcs.getStatus())) {
            account.setBak(null);
        }

        return accountDTO;
    }

    @Override
    public AccountDTO getRealAccount(String userId, String channelType) {
        if (!Account.CHANNEL_TYPE_D1.equals(channelType) && !Account.CHANNEL_TYPE_D0.equals(channelType)) {
            throw new MsgException("未知的通道类型");
        }

        Account account = new Account();
        account.setUserId(userId);
        account.setChannelType(channelType);

        return getRealAccount(account);
    }

    @Override
    public AccountDTO getRealAccount(String userId) {
        return getRealAccount(userId, Account.CHANNEL_TYPE_D1);
    }

    @Override
    public void delAccount(String userId, String channelType) {
        LambdaQueryWrapper<Account> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(Account::getUserId, userId).eq(Account::getChannelType, channelType);
        Account account = baseMapper.selectOne(qWrapper);
        if (account == null) {
            return;
        }
        removeById(account.getId());

        if (!account.getSettleType().equals(Account.SETTLE_TYPE_CORPORATE)
            && !account.getSettleType().startsWith(Account.SETTLE_TYPE_PRIVATE_LEGAL)) {
            LambdaQueryWrapper<Account> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.eq(Account::getUserId, userId)
                    .eq(Account::getIdCardId, account.getIdCardId());
            Integer countIdCardUsedAccount = baseMapper.selectCount(queryWrapper2);
            if (countIdCardUsedAccount == null || countIdCardUsedAccount == 0) {
                // idCard如果没有再被使用
                idCardService.removeById(account.getIdCardId());
            }
        }

        LambdaQueryWrapper<Account> queryWrapper2 = Wrappers.lambdaQuery();
        queryWrapper2.eq(Account::getUserId, userId).eq(Account::getBankCardId, account.getBankCardId());
        Integer countBankCardUsedAccount = baseMapper.selectCount(queryWrapper2);
        if (countBankCardUsedAccount == null || countBankCardUsedAccount == 0) {
            // bankCard如果没有再被使用
            bankCardService.removeById(account.getBankCardId());
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editAccountBankCard(BankCard bankCard) {
        UserApp userApp = new UserApp();
        userApp.setUserId(Long.parseLong(bankCard.getUserId()));
        userApp.setUserType("promoter");
        userApp = uaService.getOne(new QueryWrapper<>(userApp));

        MerchantChannelStatus mcs = mcsService.getValidData(userApp.getMerchantCode());

        MsgException.checkNull(mcs, "商户还未进件");

        MsgException.checkEquals(mcs.getStatus(), MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT, "结算银行卡正在修改审核中，暂不允许修改结算银行卡");

        // 老接口进件的无法通过接口修改结算信息
        if (mcs.getChannel().equals(4) && StringUtils.isEmpty(mcs.getApplicationId())) {
            throw new MsgException("暂不支持更换银行卡, 请联系客服进行银行卡信息变更");
        }

        AccountDTO accountDTO;
        if (mcs.getChannel() == 4) {
            accountDTO = getRealAccount(bankCard.getUserId(), Account.CHANNEL_TYPE_D0);
        } else {
            accountDTO = getRealAccount(bankCard.getUserId(), Account.CHANNEL_TYPE_D1);
        }

        if (Objects.equals(accountDTO.getSettleType(), Account.SETTLE_TYPE_CORPORATE)) {
            throw new MsgException("对公结算, 请联系客服修改");
        }

        if (accountDTO.getBankCard() != null && accountDTO.getBankCard().getBankCardNo().equals(bankCard.getBankCardNo())) {
            throw new MsgException("相同结算银行卡信息，勿需修改");
        }

        IdCard accountIdCard = idCardService.getAccountIdCard(bankCard.getUserId(), mcs.getVirChannelFlag());
        // 作银行卡四要素校验
        String certName = accountIdCard.getCertName();
        try {
            aliyunService.checkBankCorrect(bankCard.getPhone(), bankCard.getBankCardNo(), accountIdCard.getCertNo(), certName);
        } catch (MsgException e) {
            throw new MsgException("银行卡信息校验不通过，请填写结算人【" + DesensitizedUtil.chineseName(certName) + "】的银行卡");
        }

        bankCard.setBankHolder(certName);
        Account account = new Account().setChannelType(accountDTO.getChannelType());
        account.setUserId(bankCard.getUserId());
        account = getOne(new QueryWrapper<>(account));
        account.setBak((JSONObject) JSON.toJSON(bankCard));
        updateById(account);

        uaService.editMerchantAudit(bankCard.getUserId() + "");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editAccountBankCardV2(BankCardDTO bankCardDTO) {
        // 判断状态
        Account account = getRealAccount(bankCardDTO.getUserId(), bankCardDTO.getChannelType());

        MsgException.checkEquals(account.getSettleType(), Account.SETTLE_TYPE_CORPORATE, "对公结算, 不支持修改结算卡");

        UserApp ua = uaService.getOne(new LambdaQueryWrapper<UserApp>().eq(UserApp::getUserId, bankCardDTO.getUserId()));

        MerchantChannelStatus mcs = mcsService.getByMerchantCodeAndChannelType(ua.getMerchantCode(), bankCardDTO.getChannelType());

        MsgException.checkNull(mcs, "商户还未进件");

        MsgException.checkEquals(mcs.getStatus(), MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT, "结算银行卡正在修改审核中，暂不允许修改结算银行卡");

        BankCard currentData = bankCardService.getById(account.getBankCardId());
        if (currentData != null && bankCardDTO.getBankCardNo().equals(currentData.getBankCardNo())) {
            throw new MsgException("相同结算银行卡信息，勿需修改");
        }

        IdCard accountIdCard = idCardService.getById(account.getIdCardId());
        // 作银行卡四要素校验
        String certName = accountIdCard.getCertName();

        bankCardDTO.setBankHolder(certName);
        try {
            aliyunService.checkBankCorrect(bankCardDTO.getPhone(), bankCardDTO.getBankCardNo(), accountIdCard.getCertNo(), certName);
        } catch (MsgException e) {
            throw new MsgException("银行卡信息校验不通过，请填写结算人【" + DesensitizedUtil.chineseName(certName) + "】的银行卡");
        }

        BankCard bankCard = Converter.INSTANCE.toEntity(bankCardDTO);
        account.setBak((JSONObject) JSON.toJSON(bankCard));
        updateById(account);
        mcs.setStatus(MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT);
        mcsService.updateById(mcs);

        // 执行深入操作
        switch (mcs.getChannel().toString()) {
            case "1":
                // 随行付
                sxfMerchantAuditService.editMerchantAudit(bankCardDTO.getUserId());
                break;
            case "2":
                // 乐刷，暂不支持
                leshuaMerchantAuditService.editMerchantAudit(bankCardDTO.getUserId());
                break;
            case "3":
                // 瑞银信
                ryxMerchantAuditService.editMerchantAudit(bankCardDTO.getUserId());
                break;
            case "4":
                // 银盛
                // MsgException.throwException("修改商户信息请联系客服");
                // 老接口进件的无法通过接口修改结算信息
                if (StringUtils.isEmpty(mcs.getApplicationId())) {
                    MsgException.throwException("修改商户银行卡, 请联系客服");
                    return;
                }
                // 银盛
                ysAuditServiceV2.editMerchantAudit(bankCardDTO.getUserId());
                break;
            default:
                throw new MsgException("未知的进件通道");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bankcardAudit(BankInfoDTO bankInfoDTO) {
        if (bankInfoDTO.getPhone().length() > 11 || bankInfoDTO.getPhone().isEmpty()) {
            throw new MsgException("手机号格式不正确");
        }

        // 校验参数是否完整
        bankInfoDTO.setBankCardNo(bankInfoDTO.getBankCardNo().replaceAll("[ \u3000]", ""));
        bankInfoDTO.paramCheck();

        BankCard bankCard1 = BankCardConverter.INSTANCE.dto2Domain(bankInfoDTO);
        bankCardService.checkBankInfo(bankCard1);

        // 查询当前用户是否存在
        UserApp userApp = uaService.queryUserAppByToken();
        IdCard idCard = idCardService.getCertIdCard(bankInfoDTO.getUserId());
        MsgException.checkNull(idCard, "请先进行身份实名认证");

        BankCard bankCard = new BankCard();
        bankCard.setUserId(bankInfoDTO.getUserId());
        bankCard.setAccountType(BankCard.ACCOUNT_TYPE_CERT);
        BankCard existBankCard = bankCardService.getOne(new QueryWrapper<>(bankCard));

        if (existBankCard != null) {
            bankCard = existBankCard;
        }

        Converter.INSTANCE.cp(bankInfoDTO, bankCard);
        BeanUtils.copyProperties(bankInfoDTO, bankCard);
        bankCard.setAccountType(BankCard.ACCOUNT_TYPE_CERT);

        if (bankInfoDTO.getBankAddress() != null) {
            String[] split = bankInfoDTO.getBankAddress().split(",");
            bankCard.setBranchProvince(split[0]);
            if (split.length < 3) {
                bankCard.setBranchCity(split[0]);
                bankCard.setBranchArea(split[1]);
            } else {
                bankCard.setBranchCity(split[1]);
                bankCard.setBranchArea(split[2]);
            }
        } else {
            MsgException.checkNull(bankInfoDTO.getBranchProvince(), "缺少开户省");
            MsgException.checkNull(bankInfoDTO.getBranchCity(), "缺少开户市");
            MsgException.checkNull(bankInfoDTO.getBranchArea(), "缺少开户区");

            bankCard.setBranchProvince(bankInfoDTO.getBranchProvince());
            bankCard.setBranchCity(bankInfoDTO.getBranchCity());
            bankCard.setBranchArea(bankInfoDTO.getBranchArea());
        }

        bankCard.setImgUrl(bankInfoDTO.getBankCardFrontPic());
        if (bankInfoDTO.getBankCardFrontPic() == null) {
            bankCard.setImgUrl(bankInfoDTO.getImgUrl());
        }

        Notice notice = new Notice(1, 5, userApp);
        //TODO 银行卡认证先绕过四要素检测
        try {
            aliyunService.checkBankCorrectNow(bankInfoDTO.getPhone(), bankInfoDTO.getBankCardNo(), idCard.getCertNo(), idCard.getCertName());
        } catch (MsgException e) {
            notice = new Notice(1, 5, userApp);
            notice.setConrtent("很遗憾你的银行卡认证未通过，请您核对信息后重新提交审核！");
            // 审核失败
            userApp.setBankStatus(2);
            // 审核失败原因
            userApp.setBankReason(e.getMessage());
            noticeService.saveNotice(notice);
            uaService.updateById(userApp);
            List<String> alias = new ArrayList<>();
            alias.add(userApp.getUserId().toString());
            String notificationContent = "很遗憾你的银行卡认证未通过，请您核对信息后重新提交审核！";
            generalPushUtil.sendAllPlatByAlias(alias, "银行卡认证通知", notificationContent, "1");
            throw e;
        }

        bankCard.setBankHolder(idCard.getCertName());
        bankCardService.saveCertBankCard(bankCard);

        String spreadFlag = "1";
        if ("agent".equals(userApp.getUserType()) && "ZY_BST".equals(userApp.getRoleCode())) {
            IdCard condition = new IdCard().setCertNo(idCard.getCertNo()).setUserType(IdCard.TYPE_CERT);
            List<IdCard> idCardList = idCardService.list(new QueryWrapper<>(condition).select(" DISTINCT userId"));
            for (IdCard item : idCardList) {
                UserApp otherUa = uaService.getUserAppByUserId(item.getUserId());
                otherUa.setSpreadFlag("0");
                uaService.updateById(otherUa);
            }
        } else {
            int agentCount = idCardService.getAgentCount(idCard.getCertNo(), userApp.getUserId() + "");
            if (agentCount > 0) {
                spreadFlag = "0";
            }
        }

        userApp.setSpreadFlag(spreadFlag);
        // 删除审核失败原因
        userApp.setBankReason("");
        // 审核通过
        userApp.setBankStatus(3);
        // 实名认证通过
        userApp.setStatus(3);
        userApp.setUserName(idCard.getCertName());

        notice.setConrtent("审核通过！");

        noticeService.saveNotice(notice);
        uaService.updateById(userApp);

        // 调用极光通知推送
//        List<String> alias = new ArrayList<>();
//        alias.add(userApp.getUserId().toString());
//        generalPushUtil.sendAllPlatByAlias(alias, "银行卡认证通知", "审核通过", "1");
    }

    @Override
    public boolean canEditBankCard(String merchantCode) {
        MerchantChannelStatus merchantChannelStatus = new MerchantChannelStatus();
        merchantChannelStatus.setMerchantCode(merchantCode);
        val qWrapper = new QueryWrapper<>(merchantChannelStatus);
        qWrapper.orderByDesc("valid")
                .orderByAsc("createTime")
                .last("limit 1");
        merchantChannelStatus = mcsService.getOne(qWrapper);

        UserApp userApp = new UserApp();
        userApp.setMerchantCode(merchantCode).setUserType("promoter");
        userApp = uaService.queryUserApp(userApp);

        Account account = new Account();
        account.setUserId(userApp.getUserId() + "");

        account = getOne(new QueryWrapper<>(account));

        if (account == null) {
            throw new MsgException("未获取到结算信息");
        }

        // 只有小微商户和对私法人结算才可以通过app修改结算账户
        String settleType = account.getSettleType();
        boolean flag = settleType.equals(Account.SETTLE_TYPE_MICRO_STORE) || settleType.startsWith(Account.SETTLE_TYPE_PRIVATE_LEGAL);
        // 修改审核中的商户不能操作
        boolean statusFlag = MerchantChannelStatus.AUDIT_STATUS_SUCCESS.equals(merchantChannelStatus.getStatus());

        return statusFlag && flag;
    }
}
