package cn.pluss.platform.sxf.audit;

import cn.pluss.platform.SxfMccInfoService;
import cn.pluss.platform.channel.BaseMerchantAuditService;
import cn.pluss.platform.dto.AccountDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.BankCodeSxfMapper;
import cn.pluss.platform.mapper.MerchantChannelStatusMapper;
import cn.pluss.platform.merchantChannelImg.MerchantChannelImgService;
import cn.pluss.platform.merchantImage.MerchantImageService;
import cn.pluss.platform.subMerchant.SubMerchantService;
import cn.pluss.platform.sxf.SxfService;
import cn.pluss.platform.task.SxfMerAuditHandler;
import cn.pluss.platform.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author DJH
 */
@Slf4j
@Service("sxfMerchantAuditService")
@RequiredArgsConstructor
public class SxfMerchantAuditServiceImpl extends BaseMerchantAuditService {

    @Autowired
    private RestTemplate restTemplate;

    @Resource
    private BankCodeSxfMapper bankCodeSxfMapper;
    @Resource
    private MerchantChannelStatusMapper merchantChannelStatusMapper;
    @Autowired
    private MerchantChannelImgService merchantChannelImgService;
    @Autowired
    private SubMerchantService subMerchantService;

    @Lazy @Autowired
    private SxfService sxfService;

    @Autowired
    private SxfMccInfoService sxfMccInfoService;

    @Lazy @Autowired
    private SxfMerAuditHandler sxfMerAuditHandler;

    @Lazy @Autowired
    private MerchantImageService miService;

    /**
     * @param merchantImage 上传图片信息
     *                      orgId  - 机构编号;
     *                      reqId   - 请求id, uuid;
     *                      pictureType - 照片类型;   具体类型参照随行付文档;
     *                      file - 图片文件, 文件格式为mutilpartfile, 文件名为file
     */
    @Override
    public void imageUpload(MerchantImage merchantImage) {
        // MerchantChannelImg merchantChannelImg = new MerchantChannelImg()
        //         .setSrcUrl(merchantImage.getPicUrl())
        //         .setChannelType(1);
        // merchantChannelImg = merchantChannelImgService.getOne(new QueryWrapper<>(merchantChannelImg));
        // if (merchantChannelImg == null) {
        //     merchantChannelImg = new MerchantChannelImg().setSrcUrl(merchantImage.getPicUrl());
        // } else {
        //     if (merchantImage.getPicUrl().equals(merchantChannelImg.getSrcUrl())) {
        //         merchantImage.setPhotoUrl(merchantChannelImg.getChannelImgUrl());
        //         return;
        //     }
        // }

        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        byte[] bytes;

        try {
            bytes = FileUtil.url2Bytes(merchantImage.getPicUrl());
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("图片读取失败");
        }
        ByteArrayResource contentsAsResource = new ByteArrayResource(bytes) {
            @Override
            public String getFilename() {
                return UUID.randomUUID().toString().replace("-", "") + ".jpg";
            }
        };
        paramMap.add("file", contentsAsResource);
        paramMap.add("orgId", SxfConfg.ORG_ID);

        paramMap.add("pictureType", imgTypeTransform(merchantImage.getPhotoType()));

        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(paramMap, headers);
        JSONObject responseJson = restTemplate.postForObject(SxfConfg.SXF_MERCHANT_INCOME_PHOTO_UPLOAD, request, JSONObject.class);

        MsgException.checkNull(responseJson, "请求失败");
        log.info("upload response : {}", responseJson.toJSONString());

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, responseJson.get("code"), "请求失败");

        JSONObject respData = responseJson.getJSONObject("respData");

        MsgException.checkNull(respData, "上传图片失败");

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, respData.get("bizCode"), respData.getString("bizMsg"));

        Date date = new Date();

        // merchantChannelImg.setChannelImgUrl(respData.getString("PhotoUrl"))
        //         .setSrcUrl(merchantImage.getPicUrl())
        //         .setMerImgId(merchantImage.getId())
        //         .setCreateTime(date)
        //         .setUpdateTime(date)
        //         .setChannelType(1);

        // 这里将上传结果保存下来，方面外部后续接口调用
        merchantImage.setPhotoUrl(respData.getString("PhotoUrl"));
        // merchantChannelImgService.saveOrUpdate(merchantChannelImg);
    }

    @Override
    public void imageUpload(String url, String picType) {
        MerchantChannelImg merchantChannelImg = new MerchantChannelImg().setSrcUrl(url).setChannelType(1);
        merchantChannelImg = merchantChannelImgService.getOne(new QueryWrapper<>(merchantChannelImg));
        if (merchantChannelImg == null) {
            merchantChannelImg = new MerchantChannelImg().setSrcUrl(url);
        } else {
            if (url.equals(merchantChannelImg.getSrcUrl())) {
                return;
            } else {
                merchantChannelImg.setSrcUrl(url);
            }
        }

        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        byte[] bytes;

        try {
            bytes = FileUtil.url2Bytes(url);
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("图片读取失败");
        }
        ByteArrayResource contentsAsResource = new ByteArrayImg(bytes,
                UUID.randomUUID().toString().replace("-", "") + ".jpg");
        paramMap.add("file", contentsAsResource);
        paramMap.add("orgId", SxfConfg.ORG_ID);
        paramMap.add("pictureType", imgTypeTransform(picType));

        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(paramMap, headers);
        JSONObject responseJson = restTemplate.postForObject(SxfConfg.SXF_MERCHANT_INCOME_PHOTO_UPLOAD, request, JSONObject.class);
        if (responseJson == null) {
            throw new MsgException("请求失败");
        }

        log.info("upload response : {}", responseJson.toJSONString());

        if (!SxfConfg.SXF_SUCCESS_CODE.equals(responseJson.get("code"))) {
            throw new MsgException("请求失败");
        }

        JSONObject respData = responseJson.getJSONObject("respData");

        MsgException.checkNull(respData, "上传图片失败");

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, respData.get("bizCode"), respData.getString("bizMsg"));

        Date date = new Date();

        merchantChannelImg.setChannelImgUrl(respData.getString("PhotoUrl"))
                .setCreateTime(date)
                .setUpdateTime(date)
                .setChannelType(1);
        merchantChannelImgService.saveOrUpdate(merchantChannelImg);
    }

    @Override
    public void merchantAudit(String userId, boolean isFailCheck) {
        merchantAuditCheck(userId, isFailCheck);

        MerchantBaseInfo merchantBaseInfo = merchantBaseInfoService.getMerchantBaseInfoByUserId(userId);
        MerchantChannelStatus mcs = mcsService.getByMerchantCode(merchantBaseInfo.getMerchantCode(), 1);
        JSONObject reqData = new JSONObject();

        // 判断是第一次进件是入驻修改，还是第一次进件
        String targetUrl;
        MsgException.checkNull(mcs, "商户未提交审核");

        String status = mcs.getStatus();
        String thirdStatus = mcs.getThirdStatus();
        String merchantId = mcs.getMerchantId();

        if (status.equals(MerchantChannelStatus.AUDIT_STATUS_EXAMINING) && !thirdStatus.equals(MerchantChannelStatus.AUDIT_THIRD_STATUS_WAITING)) {
            MsgException.throwException("进件审核中，请等待审核结果");
        }

        if (MerchantChannelStatus.isAudited(mcs)) {
            MsgException.throwException("商户已进件成功，请勿重复进件");
        }

        if (StringUtils.isEmpty(merchantId)) {
            // 初次进件
            targetUrl = SxfConfg.SXF_MERCHANT_INCOME;
        } else {
            // 进件失败数据修改
            targetUrl = SxfConfg.SXF_UPADTE_MERCHANT_RZ;
            reqData.put("mno", merchantId);
        }

        // step 1、组合请求数据
        reqData.putAll(getMerchantAuditInfo(userId, merchantBaseInfo, mcs));
        reqData.put("callbackUrl", ParametersUtil.domain + "/api/auditCallback/sxf");

        log.info("{}随行付进件参数{}", userId, JSON.toJSONString(reqData));
        // step 2、调取通用请求
        JSONObject resultMap = sxfService.requestApi(targetUrl, reqData);
        // 请求成功, 验证签名

        try {
            checkSign(resultMap);
        } catch (Exception e) {
            MsgException.throwException(e.getMessage());
        }

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, resultMap.get("code"), "进件失败，" + resultMap.get("msg"));

        // 业务成功
        JSONObject respData = resultMap.getJSONObject("respData");
        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, respData.get("bizCode"), "进件失败，" + respData.get("bizMsg"));

        Date date = new Date();

        String applicationId = respData.getString("applicationId");
        String mno = respData.getString("mno");

        mcs.setChannel(1);
        mcs.setUpdateTime(date);
        mcs.setMerchantCode(merchantBaseInfo.getMerchantCode());
        mcs.setStatus("1");
        mcs.setThirdStatus("");
        mcs.setCallbackStatus("0");
        mcs.setRemark("随行付审核中");
        mcs.setApplicationId(applicationId);
        mcs.setMerchantId(mno);

        MerchantAuditRecord merchantAuditRecord = new MerchantAuditRecord();
        merchantAuditRecord.setStatus("1");
        merchantAuditRecord.setMerchantCode(merchantBaseInfo.getMerchantCode());
        merchantAuditRecord.setChannel(1);
        merchantAuditRecord.setThirdStatus("");
        merchantAuditRecord.setMerchantId(mno);
        merchAuditRecService.save(merchantAuditRecord);

        if (StringUtil.isNotEmpty(mcs.getId())) {
            merchantChannelStatusMapper.updateById(mcs);
        } else {
            // 保存进件信息
            merchantChannelStatusMapper.insert(mcs);
        }
    }

    @Override
    public void editMerchantAudit(String userId) {
        MerchantBaseInfo merchantBaseInfo = merchantBaseInfoService.getMerchantBaseInfoByUserId(userId);
        MerchantChannelStatus merchantChannelStatus = mcsService.getSxfMerchantStatusInfo(merchantBaseInfo.getMerchantCode());
        // step 1、组合请求数据
        JSONObject reqData = new JSONObject();
        Account account = new Account().setUserId(userId).setChannelType(Account.CHANNEL_TYPE_D1);
        account = accountService.getOne(new QueryWrapper<>(account));
        IdCard accountIdCard = idCardService.getAccountIdCard(userId, Account.CHANNEL_TYPE_D1);
        JSONObject bak = account.getBak();

        reqData.put("mno", merchantChannelStatus.getMerchantId());
        reqData.put("actTyp", "01");
        reqData.put("stmManIdNo", accountIdCard.getCertNo());
        reqData.put("actNo", bak.get("bankCardNo"));

        String contactLine = (String) bak.get("contactLine");
        MsgException.checkBlank(contactLine, "修改的银行卡信息缺少联行号");

        BankCodeSxf bankCodeSxf = new BankCodeSxf();
        bankCodeSxf.setCnapsCode(contactLine);
        bankCodeSxf = bankCodeSxfMapper.selectOne(new QueryWrapper<>(bankCodeSxf));

        MsgException.checkNull(bankCodeSxf, "修改的银行卡，无法获取对应的支行信息");
        reqData.put("depoBank", bankCodeSxf.getBankCode());
        reqData.put("depoProvCd", bankCodeSxf.getProvinceCode());
        reqData.put("depoCityCd", bankCodeSxf.getCityCode());
        reqData.put("lbnkNo", bankCodeSxf.getCnapsCode());
        reqData.put("lbnkNm", bankCodeSxf.getCnapsName());
        reqData.put("actNm", bak.get("bankHolder"));

        MerchantImage merchantImage = new MerchantImage();
        merchantImage.setPicUrl(bak.getString("imgUrl"));
        merchantImage.setPhotoType(MerchantImage.ImageType.BANK_CARD_FRONT);
        imageUpload(merchantImage);

        reqData.put("bankCardPositivePic", merchantImage.getPhotoUrl());
        reqData.put("updateCallBackUrl", ParametersUtil.domain + "/api/auditCallback/sxf/edit");
        String targetUrl = SxfConfg.SXF_UPDATE_MERCHANT_INFO;
        // step 2、调取通用请求
        JSONObject resultMap = sxfService.requestApi(targetUrl, reqData);
        // 请求成功, 验证签名
        try {
            checkSign(resultMap);
        } catch (Exception e) {
            throw new MsgException(e.getMessage());
        }

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, resultMap.get("code"), "进件修改失败，" + resultMap.get("msg"));

        // 业务成功
        JSONObject respData = resultMap.getJSONObject("respData");
        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, respData.get("bizCode"), "进件修改失败，" + respData.get("bizMsg"));

        // 保存商户进件修改记录
        MerchantAuditRecord updateRecord = new MerchantAuditRecord();
        updateRecord.setMerchantId(merchantChannelStatus.getMerchantId());
        updateRecord.setApplicationId(respData.getString("applicationId"));
        updateRecord.setChannel(1);
        updateRecord.setStatus("1");
        updateRecord.setMerchantCode(merchantBaseInfo.getMerchantCode());
        // 文档上没有返回状态码
        merchAuditRecService.save(updateRecord);
        // 修改商户状态
        merchantChannelStatus.setStatus(MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT);
        merchantChannelStatus.setApplicationId(respData.getString("applicationId"));
        mcsService.updateById(merchantChannelStatus);
    }

    @Override
    public JSONObject merchantAuditResult(Map<String, Object> result) throws Exception {
        MsgException.check(result.isEmpty(), "参数为空！");

        Object merchantId = result.get("merchantId");
        MsgException.checkNull(merchantId, "商户编号不能为空！");
        JSONObject reqData = new JSONObject(1);
        reqData.put("mno", merchantId);
        log.info("=================>【随行付】商户详情信息获取接口，请求业务参数:{}<====================", reqData);
        JSONObject resultMap = sxfService.requestApi(SxfConfg.SXF_QUERY_MERCHANT_DETAIL, reqData);
        checkSign(resultMap);

        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, resultMap.get("code"), resultMap.getString("msg"));

        // 业务成功
        JSONObject respData = resultMap.getJSONObject("respData");
        MsgException.checkUnequals(SxfConfg.SXF_SUCCESS_CODE, respData.get("bizCode"), respData.getString("bizMsg"));

        JSONArray repoInfo = respData.getJSONArray("repoInfo");
        if (repoInfo != null && !repoInfo.isEmpty()) {
            for (Object o : repoInfo) {
                Map<String, String> item = (Map<String, String>) o;
                if ("WX".equalsIgnoreCase(item.get("childNoType"))) {
                    QueryWrapper<SubMerchant> subMerchantQueryWrapper = new QueryWrapper<SubMerchant>()
                            .eq("merchantId", merchantId).eq("subMchType", "WX");
                    SubMerchant wxInfo = subMerchantService.getOne(subMerchantQueryWrapper);
                    String wxStatus = item.get("repoStatus");
                    String wxCildNo = null;
                    String wxChannelId = null;
                    String wxErrorMsg = null;

                    // 接入成功
                    if ("01".equals(item.get("repoStatus"))) {
                        wxCildNo = item.get("childNo");
                        wxChannelId = item.get("channelId");
                    } else {
                        wxErrorMsg = item.get("errMessage");
                    }
                    resultMap.put("wxCildNo", wxCildNo);
                    resultMap.put("wxChannelId", wxChannelId);
                    if (wxInfo == null) {
                        SubMerchant wxSubMerchant = new SubMerchant();
                        wxSubMerchant.setMerchantId(merchantId.toString());
                        wxSubMerchant.setChannelId(wxChannelId);
                        wxSubMerchant.setSubMchId(wxCildNo);
                        wxSubMerchant.setSubMchType("WX");
                        wxSubMerchant.setRemark(wxErrorMsg);
                        wxSubMerchant.setChannelTypeId("1");
                        wxSubMerchant.setStatus(wxStatus);
                        wxSubMerchant.setCreateTime(new Date());
                        subMerchantService.save(wxSubMerchant);
                    } else {
                        wxInfo.setStatus(wxStatus);
                        wxInfo.setUpdateTime(new Date());
                        wxInfo.setRemark(wxErrorMsg);
                        wxInfo.setSubMchId(wxCildNo);
                        wxInfo.setChannelId(wxChannelId);
                        subMerchantService.updateById(wxInfo);
                    }
                } else if ("ZFB".equalsIgnoreCase(item.get("childNoType"))) {
                    QueryWrapper<SubMerchant> subMerchantQueryWrapper = new QueryWrapper<SubMerchant>()
                            .eq("merchantId", merchantId).eq("subMchType", "ZFB");
                    SubMerchant subZfbInfo = subMerchantService.getOne(subMerchantQueryWrapper);
                    String zfbStatus = item.get("repoStatus");
                    String zfbChildNo = null;
                    String zfbChannelId = null;
                    String zfbErrorMsg = null;
                    if ("01".equals(item.get("repoStatus"))) {
                        zfbChildNo = item.get("childNo");
                        zfbChannelId = item.get("channelId");
                    } else {
                        zfbErrorMsg = item.get("errMessage");
                    }
                    resultMap.put("zfbChildNo", zfbChildNo);
                    resultMap.put("zfbChannelId", zfbChannelId);
                    if (subZfbInfo == null) {
                        SubMerchant subMerchant = new SubMerchant();
                        subMerchant.setMerchantId(merchantId.toString());
                        subMerchant.setChannelId(zfbChannelId);
                        subMerchant.setSubMchId(zfbChildNo);
                        subMerchant.setSubMchType("ZFB");
                        subMerchant.setRemark(zfbErrorMsg);
                        subMerchant.setChannelTypeId("1");
                        subMerchant.setStatus(zfbStatus);
                        subMerchant.setCreateTime(new Date());
                        subMerchantService.save(subMerchant);
                    } else {
                        subZfbInfo.setStatus(zfbStatus);
                        subZfbInfo.setUpdateTime(new Date());
                        subZfbInfo.setRemark(zfbErrorMsg);
                        subZfbInfo.setSubMchId(zfbChildNo);
                        subZfbInfo.setChannelId(zfbChannelId);
                        subMerchantService.updateById(subZfbInfo);
                    }
                }
            }
        }
        return resultMap;
    }

    @Override
    public JSONObject merchantAuditCallback(JSONObject auditResult) throws Exception {
        log.info("随行付商户入驻回调, 商户编号为{}， ：\n {}", auditResult.getString("mno"), auditResult.toJSONString());
        checkSign(auditResult);
        try {
            // 异步处理
            sxfMerAuditHandler.auditHandler(auditResult);
        } catch (Exception e) {
            log.error("入驻回调异步任务启动失败!");
            e.printStackTrace();
        }

        return SxfConfg.ok();
    }

    @Override
    public JSONObject editMerchantCallback(JSONObject auditResult) throws Exception {
        checkSign(auditResult);
        try {
            // 异步处理
            sxfMerAuditHandler.auditEditHandler(auditResult);
        } catch (Exception e) {
            log.error("入驻回调异步任务启动失败!");
            e.printStackTrace();
        }

        return SxfConfg.ok();
    }

    @Override
    public String imgTypeTransform(String imageType) {
        switch (imageType) {
            case MerchantImage.ImageType.IDCARD_FRONT:
                return ImageType.IDCARD_FRONT;
            case MerchantImage.ImageType.IDCARD_BACK:
                return ImageType.IDCARD_BACK;
            case MerchantImage.ImageType.SETTLE_IDCARD_FRONT:
                return ImageType.SETTLE_IDCARD_FRONT;
            case MerchantImage.ImageType.SETTLE_IDCARD_BACK:
                return ImageType.SETTLE_IDCARD_BACK;
            case MerchantImage.ImageType.BANK_CARD_BACK:
                return ImageType.BANK_CARD_BACK;
            case MerchantImage.ImageType.BANK_CARD_FRONT:
                return ImageType.BANK_CARD_FRONT;
            case MerchantImage.ImageType.BUSINESS_LICENSE:
                return ImageType.BUSINESS_LICENSE;
            case MerchantImage.ImageType.ACCOUNT_PERMITS:
                return ImageType.ACCOUNT_PERMITS;
            case MerchantImage.ImageType.NON_LEG_SETTLE_AUTH:
                return ImageType.NON_LEG_SETTLE_AUTH;
            case MerchantImage.ImageType.SHOP_FRONT_DOOR:
                return ImageType.SHOP_FRONT_DOOR;
            case MerchantImage.ImageType.CASH_DESK_PHOTO:
                return ImageType.CASH_DESK_PHOTO;
            case MerchantImage.ImageType.STORE_INTERIOR_PHOTO:
                return ImageType.STORE_INTERIOR_PHOTO;
            default:
                return ImageType.OTHER;
        }
    }

    @Override
    public void checkSign(JSONObject receiveData) throws Exception {
        if (receiveData == null || receiveData.getString("sign") == null) {
            throw new MsgException("未知数据");
        }

        String srcData = SignUtils.getSignContent(receiveData);
        boolean sign = RSAUtils.checkSign(SxfConfg.PUBLIC_KEY, srcData, receiveData.getString("sign"));
        if (!sign) {
            throw new IllegalArgumentException("商户入驻回调接口验签不通过");
        }
    }

    /**
     * 组合银行卡信息， 必须的在combineMerchantBaseInfo之后调用
     *
     * @param paramMap 组合的数据
     * @param userId   用户id
     */
    private void combineBankInfo(Map<String, Object> paramMap, String userId) {
        // 结算信息
        AccountDTO accountDTO = accountService.getRealAccount(userId);
        MsgException.checkNull(accountDTO, "请完善结算信息");

        // 实名信息
        IdCard certIdCard = idCardService.getCertIdCard(userId);

        IdCard inChargeIdCard;

        if (Account.SETTLE_TYPE_MICRO_STORE.equals(accountDTO.getSettleType())) {
            // 小微商户 - 结算信息中的身份信息即商户负责人信息
            inChargeIdCard = accountDTO.getIdcard();
        } else {
            // 其他的负责人信息是法人信息
            inChargeIdCard = idCardService.getLegalIdCard(userId);
        }

        BankCard bankCard = accountDTO.getBankCard();
        paramMap.put("identityName", inChargeIdCard.getCertName());
        paramMap.put("identityTyp", inChargeIdCard.getCertType());
        paramMap.put("identityNo", inChargeIdCard.getCertNo());


        if ("01".equals(paramMap.get("haveLicenseNo"))) {
            // 小微商户
            paramMap.put("stmManIdNo", certIdCard.getCertNo());
            paramMap.put("actTyp", "01");
        } else {
            // 非小微商户，可以
            paramMap.put("actTyp", BankCard.ACCOUNT_TYPE_CORPORATE.equals(bankCard.getAccountType()) ? "00" : "01");

            if (accountDTO.getSettleType() == null) {
                throw new MsgException("缺少结算信息(若无填写结算信息界面，请更新app)");
            }

            IdCard idCard = accountDTO.getIdcard();
            if (idCard == null) {
                idCard = certIdCard;
            }
            // 对私需要传递
            if ("01".equals(paramMap.get("actTyp"))) {
                paramMap.put("stmManIdNo", idCard.getCertNo());
            }
        }

        paramMap.put("actNm", bankCard.getBankHolder());
        paramMap.put("actNo", bankCard.getBankCardNo());
        paramMap.put("accountLicStt", inChargeIdCard.getCertStartTime());
        paramMap.put("accountLicEnt", inChargeIdCard.getCertEndTime());

        QueryWrapper<BankCodeSxf> queryWrapper = new QueryWrapper<BankCodeSxf>().eq("cnaps_code", bankCard.getContactLine());
        BankCodeSxf bankCodeSxf = bankCodeSxfMapper.selectOne(queryWrapper);
        // 银行code
        paramMap.put("depoBank", bankCodeSxf.getBankCode());
        // 省份code
        paramMap.put("depoProvCd", bankCodeSxf.getProvinceCode());
        // 城市code
        paramMap.put("depoCityCd", bankCodeSxf.getCityCode());
        // 联行号
        paramMap.put("lbnkNo", bankCodeSxf.getCnapsCode());
    }

    private void combineMerchantBaseInfo(Map<String, Object> map, MerchantBaseInfo merchantBaseInfo) {
        String mcc = merchantBaseInfo.getMcc();
        SxfMccInfo sxfMccInfo = sxfMccInfoService.getByMccCode(mcc);
        map.put("mecDisNm", merchantBaseInfo.getAlias());
        map.put("mblNo", merchantBaseInfo.getContactMobile());

        if (sxfMccInfo == null) {
            map.put("operationalType", "01");
        } else {
            // 判断经营类型
            switch (sxfMccInfo.getFMccType()) {
                case "线上":
                    //TODO 如果渠道判定魏线上则 onlineType onlineName为必填
                    map.put("operationalType", "02");
                    break;
                case "非盈利":
                    map.put("operationalType", "03");
                    break;
                case "缴费类":
                    map.put("operationalType", "04");
                    break;
                case "保险":
                    map.put("operationalType", "05");
                    break;
                case "私立院校":
                    map.put("operationalType", "06");
                    break;
                default:
                    map.put("operationalType", "01");
                    break;
            }
        }

        // 商户类型
        switch (merchantBaseInfo.getMerchantType()) {
            case "1":
                map.put("haveLicenseNo", "01");
                map.put("actTyp", "01");
                break;
            case "2":
                map.put("haveLicenseNo", "02");
                map.put("registCode", merchantBaseInfo.getBussAuthNum());
                map.put("cprRegNmCn", merchantBaseInfo.getBussAuthName());
                break;
            case "3":
                map.put("haveLicenseNo", "03");
                map.put("registCode", merchantBaseInfo.getBussAuthNum());
                map.put("cprRegNmCn", merchantBaseInfo.getBussAuthName());
                map.put("licenseMatch", "00");
                break;
            default:
                throw new MsgException("未知商户类型");
        }
        map.put("mecTypeFlag", "00");

        map.put("cprRegAddr", merchantBaseInfo.getAddress());

        String province = merchantBaseInfo.getProvince();
        String city = merchantBaseInfo.getCity();
        String area = merchantBaseInfo.getDistrict();
        RegionCodeSxf regionCodeSxf = regionReflectService.getSxfRegionCode(province, city, area);

        map.put("regProvCd", regionCodeSxf.getProvinceCode());
        map.put("regCityCd", regionCodeSxf.getCityCode());
        map.put("regDistCd", regionCodeSxf.getAreaCode());

        map.put("mccCd", mcc);
        map.put("csTelNo", merchantBaseInfo.getContactMobile());
    }

    private void combineCommon(Map<String, Object> map) {
        Map<String, Object> rateMap = new HashMap<>();
        List<Map<String, Object>> qrCodeList = new LinkedList<>();
        // 微信
        rateMap.put("rate", "0.38");
        rateMap.put("rateType", "01");
        qrCodeList.add(rateMap);
        // 支付宝
        rateMap = new HashMap<>();
        rateMap.put("rate", "0.38");
        rateMap.put("rateType", "02");
        qrCodeList.add(rateMap);
        // 银联小于1000
        rateMap = new HashMap<>();
        rateMap.put("rate", "0.40");
        rateMap.put("rateType", "06");
        qrCodeList.add(rateMap);
        // 银联大于1000
        rateMap = new HashMap<>();
        rateMap.put("rate", "0.6");
        rateMap.put("rateType", "07");
        qrCodeList.add(rateMap);

        map.put("qrcodeList", qrCodeList);
        // 03 T1  04 D1
        map.put("settleType", "04");
    }

    private void combineImage(Map<String, Object> paramMap, List<MerchantImage> merchantImageList, String actTyp, String merchantType) {
        for (MerchantImage merchantImage : merchantImageList) {
            combineImage(paramMap, merchantImage, actTyp, merchantType);
        }
    }

    private void combineImage(Map<String, Object> paramMap, MerchantImage merchantImage, String actTyp, String merchantType) {
        // 非小微商户，必须传营业执照
        switch (merchantImage.getPhotoType()) {
            case MerchantImage.ImageType.IDCARD_FRONT:
                // 法人身份证正面
                paramMap.put("legalPersonidPositivePic", merchantImage.getPhotoUrl());
                break;
            case MerchantImage.ImageType.IDCARD_BACK:
                paramMap.put("legalPersonidOppositePic", merchantImage.getPhotoUrl());
                break;
            case MerchantImage.ImageType.SETTLE_IDCARD_FRONT:
                if (BankCard.ACCOUNT_TYPE_PRIVATE.equals(paramMap.get("actTyp"))) {
                    // 对私需要传结算人身份证
                    paramMap.put("settlePersonIdcardPositive", merchantImage.getPhotoUrl());
                }
                break;
            case MerchantImage.ImageType.SETTLE_IDCARD_BACK:
                if (BankCard.ACCOUNT_TYPE_PRIVATE.equals(paramMap.get("actTyp"))) {
                    // 对私需要传结算人身份证
                    paramMap.put("settlePersonIdcardOpposite", merchantImage.getPhotoUrl());
                }
                break;
            case MerchantImage.ImageType.SHOP_FRONT_DOOR:
                paramMap.put("storePic", merchantImage.getPhotoUrl());
                break;
            case MerchantImage.ImageType.STORE_INTERIOR_PHOTO:
                paramMap.put("insideScenePic", merchantImage.getPhotoUrl());
                break;
            case MerchantImage.ImageType.ACCOUNT_PERMITS:
                if (!"01".equals(actTyp)) {
                    // 对公结算需传开户许可证
                    paramMap.put("openingAccountLicensePic", merchantImage.getPhotoUrl());
                }
                break;
            case MerchantImage.ImageType.BANK_CARD_FRONT:
                if ("01".equals(actTyp)) {
                    // 对私需要传银行卡
                    paramMap.put("bankCardPositivePic", merchantImage.getPhotoUrl());
                }
                break;
            case MerchantImage.ImageType.BUSINESS_LICENSE:
                if (!"1".equals(merchantType)) {
                    paramMap.put("licensePic", merchantImage.getPhotoUrl());
                }
                break;
            case MerchantImage.ImageType.NON_LEG_SETTLE_AUTH:
                // 对私 结算人与法人的身份证证件不一致时需要提交
                if (BankCard.ACCOUNT_TYPE_PRIVATE.equals(paramMap.get("actTyp")) && !paramMap.get("identityNo").equals(paramMap.get("stmManIdNo"))) {
                    paramMap.put("letterOfAuthPic", merchantImage.getPhotoUrl());
                }
                break;
            default:
                break;
        }
    }


    public static class ImageType {

        private ImageType() {}

        /** 身份证正面 */
        public static final String IDCARD_FRONT = "02";
        /** 身份证反面 */
        public static final String IDCARD_BACK = "03";
        /** 营业执照 */
        public static final String BUSINESS_LICENSE = "13";
        /** 开户许可证 */
        public static final String ACCOUNT_PERMITS = "04";
        /** 门头照 */
        public static final String SHOP_FRONT_DOOR = "10";
        /** 非法人结算授权书 */
        public static final String NON_LEG_SETTLE_AUTH = "26";
        /** 其它 */
        public static final String OTHER = "19";
        /** 收银台照片 */
        public static final String CASH_DESK_PHOTO = "12";
        /** 门店内景照片 */
        public static final String STORE_INTERIOR_PHOTO = "11";
        /** 各大餐饮平台入驻 */
        public static final String MERCHANT_PLATFORM = "10";
        /** 手持身份证 */
        public static final String HAND_IDCARD_PHOTO = "15";
        /** 租赁协议一（封面） */
        public static final String TENANCY_AGREEMENTS1 = "16";
        /** 租赁合同二（面积，有效期页面） */
        public static final String TENANCY_AGREEMENTS2 = "17";
        /** 租赁合同三（签章页） */
        public static final String TENANCY_AGREEMENTS3 = "18";
        /** 银行卡正面 */
        public static final String BANK_CARD_FRONT = "05";
        /** 银行卡反面 */
        public static final String BANK_CARD_BACK = "06";
        /** 结算身份证正面 */
        public static final String SETTLE_IDCARD_FRONT = "08";
        /** 结算身份证反面 */
        public static final String SETTLE_IDCARD_BACK = "07";
    }

    private JSONObject getMerchantAuditInfo(String userId, MerchantBaseInfo merchantBaseInfo, MerchantChannelStatus merchantChannelStatus) {
        // step 1、组合请求数据
        JSONObject reqData = new JSONObject();
        MsgException.checkBlank(merchantBaseInfo.getMerchantType(), "请先填写商户资料");

        AccountDTO accountDTO = accountService.getAccount(userId);

        List<MerchantImage> merchantChannelImgList = miService.getListOfMerch(userId);

        for (MerchantImage merchantImage : merchantChannelImgList) {
            // 兼容老通道用户，切换通道后，没有相关的图片链接
            if (StringUtils.isEmpty(merchantImage.getPhotoUrl())) {
                imageUpload(merchantImage);
            }
        }

        combineMerchantBaseInfo(reqData, merchantBaseInfo);
        combineCommon(reqData);
        combineBankInfo(reqData, userId);
        // 添加添加账户类型判断，此处可能是图片驳回，故需要自己添加账号类型判断
        String actTyp = BankCard.ACCOUNT_TYPE_CORPORATE.equals(accountDTO.getBankCard().getAccountType()) ? "00" : "01";

        combineImage(reqData, merchantChannelImgList, actTyp, merchantBaseInfo.getMerchantType());

        //  入驻图片修改，去掉不能传的参数
        if (merchantChannelStatus != null && MerchantChannelStatus.AUDIT_STATUS_REVIEW_REJECT.equals(merchantChannelStatus.getStatus())) {
            reqData.remove("operationalType");
            reqData.remove("haveLicenseNo");
            reqData.remove("mecTypeFlag");
            reqData.remove("parentMno");
            reqData.remove("independentModel");
            reqData.remove("qrcodeList");
            reqData.remove("bankCardRates");
            reqData.remove("settleType");
            reqData.remove("clearTimeSts");
            reqData.remove("clearTime");
            reqData.remove("supportPayChannels");
            reqData.remove("supportTradeTypes");
            reqData.remove("activityType");
            reqData.remove("specifyWechatChannel");
            reqData.remove("specifyALiPayChannel");
            reqData.remove("onlineType");
            reqData.remove("onlineName");
            reqData.remove("onlineTypeInfo");
            reqData.remove("cprRegNmCn");
            reqData.remove("registCode");
            reqData.remove("licenseMatch");
            reqData.remove("orgCode");
            reqData.remove("taxRegNo");
            reqData.remove("businessLicStt");
            reqData.remove("businessLicEnt");
            reqData.remove("identityName");
            reqData.remove("identityTyp");
            reqData.remove("identityNo");
            reqData.remove("legalPersonLicStt");
            reqData.remove("legalPersonLicEnt");
            reqData.remove("actNm");
            reqData.remove("actTyp");
            reqData.remove("stmManIdNo");
            reqData.remove("accountLicStt");
            reqData.remove("accountLicEnt");
        }

        return reqData;
    }
}
