package com.ruoyi.klk.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.request.*;
import com.lkl.laop.sdk.utils.CommonUtil;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ImageRotator;
import com.ruoyi.common.utils.PdfUtil;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.customer.entity.Customer;
import com.ruoyi.frequency.customer.mapper.CustomerMapper;
import com.ruoyi.frequency.klkaccounattach.entity.KlkAccountAttach;
import com.ruoyi.frequency.klkaccounattach.service.KlkAccountAttachService;
import com.ruoyi.frequency.klkaccount.entity.KlkAccount;
import com.ruoyi.frequency.klkaccount.mapper.KlkAccountMapper;
import com.ruoyi.frequency.klkwithdrawalrecord.entity.KlkWithdrawalRecord;
import com.ruoyi.frequency.klkwithdrawalrecord.mapper.KlkWithdrawalRecordMapper;
import com.ruoyi.frequency.sale.entity.Sale;
import com.ruoyi.frequency.sale.mapper.SaleMapper;
import com.ruoyi.frequency.store.entity.Store;
import com.ruoyi.frequency.store.mapper.StoreMapper;
import com.ruoyi.frequency.withdrawalrecord.entity.WithdrawalRecord;
import com.ruoyi.frequency.withdrawalrecord.mapper.WithdrawalRecordMapper;
import com.ruoyi.klk.constant.KlkConstant;
import com.ruoyi.klk.controller.req.AddOrUpdateBankCardReq;
import com.ruoyi.klk.controller.req.GetBankNameReq;
import com.ruoyi.klk.controller.req.UpdateBankCardReq;
import com.ruoyi.klk.controller.req.UploadFileReq;
import com.ruoyi.klk.controller.resp.GetBankInfoResp;
import com.ruoyi.klk.controller.resp.SelectBindResultResp;
import com.ruoyi.klk.service.KlkService;
import com.ruoyi.klk.util.CommonService;
import com.ruoyi.klk.util.InitUtil;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.UserVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class KlkServiceImpl implements KlkService {

    @Value("${basepath.url}")
    private String urlPrefix;

    @Autowired
    private CommonService commonService;

    /**
     * 附件上传
     */
    public String uploadFile(UploadFileReq req) {
        try {
            initUtil.doInit();
            V2MmsOpenApiUploadFile v2MmsOpenApiUploadFile = new V2MmsOpenApiUploadFile();
            v2MmsOpenApiUploadFile.setVersion(KlkConstant.VERSION);
            v2MmsOpenApiUploadFile.setOrderNo(CommonUtil.getOrderNo());
            v2MmsOpenApiUploadFile.setOrgCode(KlkConstant.ORG_CODE);
            v2MmsOpenApiUploadFile.setAttType(req.getAttType());
            v2MmsOpenApiUploadFile.setAttExtName(req.getAttExtName());
            v2MmsOpenApiUploadFile.setAttContext(req.getAttContext());
            String response = LKLSDK.httpPost(v2MmsOpenApiUploadFile);
            // 解析结果
            JSONObject jsonObject = JSON.parseObject(response);
            if ("000000".equals(jsonObject.getString("retCode"))) {
                JSONObject respData = jsonObject.getJSONObject("respData");
                return respData.getString("attFileId");
            }
        } catch (Exception e) {
            log.error("附件上传出现异常：{}", e.getMessage());
        }
        throw new RuntimeException();
    }

    /**
     * 添加或修改银行卡信息
     */
    @Override
    public ResponseData addOrUpdateBankCard(AddOrUpdateBankCardReq req, UserVo userVo) {

        // 如果当前银行卡绑定失败，则删除数据库记录
        KlkAccount klkAccount = klkAccountMapper.selectOne(new LambdaQueryWrapper<KlkAccount>()
                .eq(KlkAccount::getDelFlag, PublicCommon.启用)
                .eq(KlkAccount::getUserType, userVo.getUserType())
                .eq(KlkAccount::getUserId, userVo.getUserId()));
        if (klkAccount != null && klkAccount.getBindStatus() != 3) {
            klkAccountAttachService.getBaseMapper().delete(new LambdaQueryWrapper<KlkAccountAttach>()
                    .eq(KlkAccountAttach::getDelFlag, PublicCommon.启用)
                    .eq(KlkAccountAttach::getLakalaAccountId, klkAccount.getId()));
            klkAccountMapper.deleteById(klkAccount.getId());
            req.setId(null);
        }


        // 根据上传id判断是新增还是修改
        if (req.getId() == null) {
            //新增
            return addBankCard(req, userVo);
        } else {
            //修改
            UpdateBankCardReq updateReq = new UpdateBankCardReq();
            BeanUtils.copyProperties(req, updateReq);
            return updateBankCard(updateReq, userVo);
        }
    }

    /**
     * 添加银行卡信息
     *
     * @param req
     * @param userVo
     * @return
     */
    private ResponseData addBankCard(AddOrUpdateBankCardReq req, UserVo userVo) {
        try {
            //1、调用三方接口创建卡拉卡账号
            String account = createAccount(req, userVo);

            //2、调用三方接口绑定分账关系
            bindAccount(account, req, userVo);

            return ResponseData.success("添加银行卡已受理，请等待审核结果！");

        } catch (Exception e) {
            throw new RuntimeException("添加银行卡失败，失败原因：" + e.getMessage());
        }
    }


    @Autowired
    private InitUtil initUtil;

    /**
     * 分账关系绑定申请
     *
     * @param account
     * @param req
     */
    private void bindAccount(String account, AddOrUpdateBankCardReq req, UserVo userVo) throws Exception {
        initUtil.doInit();
        V2MmsLedgerApplyBindRequest request = new V2MmsLedgerApplyBindRequest();
        request.setVersion(KlkConstant.VERSION);
        request.setOrderNo(CommonUtil.getOrderNo());

        // 将orderNo存入表中
        LambdaUpdateWrapper<KlkAccount> updateWrapper = new LambdaUpdateWrapper<KlkAccount>()
                .set(KlkAccount::getBindOrderNo, request.getOrderNo())
                .eq(KlkAccount::getUserType, userVo.getUserType())
                .eq(KlkAccount::getUserId, userVo.getUserId());


        request.setOrgCode(KlkConstant.ORG_CODE);
        request.setMerCupNo(merchantNo);
        request.setReceiverNo(account);
        // 获取合作协议对象
        AddOrUpdateBankCardReq.Attach attach = getAgreement(userVo, req);
        request.setEntrustFileName(attach.getAttachName());
        request.setEntrustFilePath(attach.getAttachStorePath());
        request.setRetUrl(urlPrefix + KlkConstant.BIND_ACC_URL);
        String response = LKLSDK.httpPost(request);
        JSONObject jsonObject = JSON.parseObject(response);
        if (!"000000".equals(jsonObject.getString("retCode"))) {
            updateWrapper.set(KlkAccount::getBindStatus, 4)
                    .set(KlkAccount::getBindFailReason, jsonObject.getString("retMsg"));
            klkAccountMapper.update(null, updateWrapper);
            throw new RuntimeException(jsonObject.getString("retMsg"));
        }
        JSONObject respData = jsonObject.getJSONObject("respData");
        updateWrapper.set(KlkAccount::getBindStatus, 2)
                .set(KlkAccount::getApplyId, respData.getString("applyId"));
        klkAccountMapper.update(null, updateWrapper);
    }

    @Autowired
    private BusinessUtil businessUtil;

    @Value("${lalkla.basePath}")
    private String basePath;

    @Value("${lalkla.filePath}")
    private String filePath;

    /**
     * 获取合作协议对象
     *
     * @return
     */
    @SneakyThrows
    private AddOrUpdateBankCardReq.Attach getAgreement(UserVo userVo, AddOrUpdateBankCardReq addOrUpdateBankCardReq) {
        String targetUrl = null;
        if (userVo.getUserType().equals(UserEnums.store.getCode())) {
            targetUrl = filePath + "storeDivideAccountsAgreement.docx";
        } else if (userVo.getUserType().equals(UserEnums.sale.getCode())) {
            targetUrl = filePath + "saleDivideAccountsAgreement.docx";
        }


        AddOrUpdateBankCardReq.Attach attach = new AddOrUpdateBankCardReq.Attach();
        attach.setAttachName("divideAccountsAgreement.pdf");
        UploadFileReq req = new UploadFileReq();
        req.setAttType("XY");
        req.setAttExtName("pdf");

        String outWordPath = basePath + UUID.randomUUID() + ".docx";
        convertHtmlToImage(addOrUpdateBankCardReq, targetUrl, outWordPath);

        String oupPdfPath = basePath + UUID.randomUUID() + ".pdf";

        PdfUtil.doc2pdf(outWordPath, oupPdfPath, filePath + "license.xml");
        FileInputStream fileInputStream = new FileInputStream(oupPdfPath);
        req.setAttContext(commonService.fileToBase64(fileInputStream));

        attach.setAttachStorePath(uploadFile(req));
        return attach;
    }


    public void convertHtmlToImage(AddOrUpdateBankCardReq req, String input, String outPut) throws Exception {

        // 创建XWPFDocument对象，加载Word文档
        XWPFDocument doc = new XWPFDocument(new FileInputStream(input));
        // 获取文档中的所有段落
        List<XWPFParagraph> paragraphs = doc.getParagraphs();

        Integer year = 5;

        Date date = DateUtil.offsetMonth(new Date(), year * 12);

        // 遍历所有段落，找到需要修改的内容
        for (XWPFParagraph paragraph : paragraphs) {
            if (StrUtil.isBlank(paragraph.getText())) {
                continue;
            }
            List<XWPFRun> runs = paragraph.getRuns();
            for (XWPFRun run : runs) {
                String text = run.text();
                if (StrUtil.isBlank(text)) {
                    continue;
                }
                String newText = text;
                if (newText.contains("${store.name}")) {
                    newText = newText.replace("${store.name}", req.getAcctName());
                }
                if (newText.contains("${store.idno}")) {
                    newText = newText.replace("${store.idno}", req.getAcctCertificateNo());
                }
                if (newText.contains("${year}")) {
                    newText = newText.replace("${year}", (year + ""));
                }
                if (newText.contains("${beginYear}")) {
                    newText = newText.replace("${beginYear}", (DateUtil.year(new Date()) + ""));
                }
                if (newText.contains("${beginMonth}")) {
                    newText = newText.replace("${beginMonth}", (DateUtil.month(new Date()) + 1) + "");
                }
                if (newText.contains("${beginDay}")) {
                    newText = newText.replace("${beginDay}", (DateUtil.dayOfMonth(new Date()) + ""));
                }
                if (newText.contains("${endYear}")) {
                    newText = newText.replace("${endYear}", (DateUtil.year(date) + ""));
                }
                if (newText.contains("${endMonth}")) {
                    newText = newText.replace("${endMonth}", (DateUtil.month(date) + 1) + "");
                }
                if (newText.contains("${endDay}")) {
                    newText = newText.replace("${endDay}", (DateUtil.dayOfMonth(date) + ""));
                }
                if (newText.contains("${endDay}")) {
                    newText = newText.replace("${endDay}", (DateUtil.dayOfMonth(date) + ""));
                }
                if (newText.contains("${date-qy}")) {
                    newText = newText.replace("${date-qy}", (DateUtil.formatDate(date) + ""));
                }
                run.setText(newText, 0);
            }
            String text = paragraph.getText();
            if (StrUtil.isNotBlank(text) && text.contains("签字/盖章") && StrUtil.isNotBlank(req.getSignature())) {
                String targetImage = basePath + UUID.randomUUID() + ".png";

                download(req.getSignature(), targetImage);
                // 图片文件
                FileInputStream imageStream = new FileInputStream(getPositionTrueImage(targetImage));
                XWPFRun provincialInfoPicRun = paragraph.createRun();
                provincialInfoPicRun.addPicture(imageStream, 5, "", Units.toEMU(80), Units.toEMU(40));
            }

        }
        // 保存修改后的文档
        FileOutputStream out = new FileOutputStream(outPut);
        doc.write(out);
        out.close();
    }

    private String getPositionTrueImage(String image) {

        String s = ImageRotator.rotate90DegreesCounterClockwise(image, basePath);
        s = ImageRotator.rotate90DegreesCounterClockwise(s, basePath);
        s = ImageRotator.rotate90DegreesCounterClockwise(s, basePath);
        return s;
    }


    public static void main(String[] args) throws Exception {

    }


    public static String getSuffix(String fileName) {
        String[] split = fileName.split("\\.");
        String suffix = ".jpg";
        if (split.length > 1) {
            suffix = "." + split[split.length - 1];
        }
        return suffix;
    }

    /**
     * 自动拼接后缀名 如sourceUrl：abc.jpg, targetUrl:cc 则存储的文件名为cc.jpg
     *
     * @param sourceUrl
     * @param targetUrl
     */
    public static File download(String sourceUrl, String targetUrl) throws Exception {
        if (new File(targetUrl).exists()) {
            new File(targetUrl).delete();
        }
        URL httpUrl = new URL(sourceUrl);
        File file = new File(targetUrl);
        FileUtils.copyURLToFile(httpUrl, file);

        return new File(targetUrl);
    }

    @Autowired
    private KlkAccountMapper klkAccountMapper;

    @Autowired
    private KlkAccountAttachService klkAccountAttachService;

    /**
     * 创建卡拉卡账号
     *
     * @param req
     * @return
     */
    public String createAccount(AddOrUpdateBankCardReq req, UserVo userVo) throws Exception {
        // 步骤一：分账接收方创建申请
        initUtil.doInit();
        V2MmsApplyLedgerReceiverRequest request = new V2MmsApplyLedgerReceiverRequest();
        request.setVersion(KlkConstant.VERSION);
        request.setOrderNo(CommonUtil.getOrderNo());
        request.setOrgCode(KlkConstant.ORG_CODE);
        request.setReceiverName(req.getAcctName());
        request.setContactMobile(selectMobileByUserType(userVo));
        request.setAcctNo(req.getAcctNo());
        request.setAcctName(req.getAcctName());
        request.setAcctTypeCode(KlkConstant.ACC_TYPE);
        request.setAcctCertificateType(KlkConstant.ACC_CERT_TYPE);
        request.setAcctCertificateNo(req.getAcctCertificateNo());
        // 步骤二：调用卡BIN接口查询信息
        Map<String, String> cardBinMap = getCardBinMap(req.getAcctNo());
        request.setAcctOpenBankCode(cardBinMap.get("acctOpenBankCode"));
        request.setAcctOpenBankName(req.getAcctOpenBankName());
        request.setAcctClearBankCode(cardBinMap.get("acctClearBankCode"));
        request.setAttachList(getAttachList(req.getAttachList()));
        String response = LKLSDK.httpPost(request);
        JSONObject jsonObject = JSON.parseObject(response);

        KlkAccount klkAccount = getKlkAccount(userVo, request);

        if ("000000".equals(jsonObject.getString("retCode"))) {
            JSONObject respData = jsonObject.getJSONObject("respData");
            klkAccount.setReceiverNo(respData.getString("receiverNo"));
            klkAccountMapper.insert(klkAccount);
            klkAccountAttachService.saveBatch(getKlkAccountAttachList(klkAccount, req));
            return respData.getString("receiverNo");
        }

        klkAccountMapper.insert(klkAccount);
        klkAccountAttachService.saveBatch(getKlkAccountAttachList(klkAccount, req));
        throw new RuntimeException(jsonObject.getString("retMsg"));
    }

    private Collection<KlkAccountAttach> getKlkAccountAttachList(KlkAccount klkAccount, AddOrUpdateBankCardReq req) {
        return req.getAttachList().stream().map(s -> {
            KlkAccountAttach klkAccountAttach = new KlkAccountAttach();
            klkAccountAttach.setLakalaAccountId(klkAccount.getId());
            klkAccountAttach.setAttachName(s.getAttachName());
            klkAccountAttach.setAttachStorePath(s.getKlkPath());
            klkAccountAttach.setHttpPath(s.getAttachStorePath());
            klkAccountAttach.setAttachType(s.getAttachType());
            return klkAccountAttach;
        }).collect(Collectors.toList());
    }


    private static KlkAccount getKlkAccount(UserVo userVo, V2MmsApplyLedgerReceiverRequest request) {
        KlkAccount klkAccount = new KlkAccount();
        klkAccount.setUserId(userVo.getUserId());
        klkAccount.setUserType(userVo.getUserType());
        klkAccount.setCreateOrderNo(request.getOrderNo());
        klkAccount.setReceiverName(request.getAcctName());
        klkAccount.setContactMobile(request.getContactMobile());
        klkAccount.setAcctNo(request.getAcctNo());
        klkAccount.setAcctName(request.getAcctName());
        klkAccount.setAcctTypeCode(request.getAcctTypeCode());
        klkAccount.setAcctCertificateType(request.getAcctCertificateType());
        klkAccount.setAcctCertificateNo(request.getAcctCertificateNo());
        klkAccount.setAcctOpenBankCode(request.getAcctOpenBankCode());
        klkAccount.setAcctOpenBankName(request.getAcctOpenBankName());
        klkAccount.setAcctClearBankCode(request.getAcctClearBankCode());
        return klkAccount;
    }

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private SaleMapper saleMapper;

    /**
     * 根据不同用户类型查询用户手机号
     *
     * @param userVo
     * @return
     */
    private String selectMobileByUserType(UserVo userVo) {
        Integer userType = userVo.getUserType();
        if (userType == 1) {//客户
            Customer customer = customerMapper.selectById(userVo.getUserId());
            return customer.getMobile();
        } else if (userType == 2) {//表现师
            Store store = storeMapper.selectById(userVo.getUserId());
            return store.getMobile();
        } else if (userType == 3) {//销售
            Sale sale = saleMapper.selectById(userVo.getUserId());
            return sale.getMobile();
        } else {
            return "";
        }
    }

    /**
     * 获取附件信息
     * 将前端传的信息转换为三方接口需要的信息
     *
     * @param attachList
     * @return
     */
    private List<V2MmsApplyLedgerReceiverRequest.AttachInfo> getAttachList(List<AddOrUpdateBankCardReq.Attach> attachList) {
        return attachList.stream().map(s -> {
            V2MmsApplyLedgerReceiverRequest.AttachInfo attachInfo = new V2MmsApplyLedgerReceiverRequest.AttachInfo();
            attachInfo.setAttachName(s.getAttachName());
            attachInfo.setAttachType(commonService.getAttType(s.getAttachType()));
            UploadFileReq req = new UploadFileReq();
            req.setAttType(attachInfo.getAttachType());
            req.setAttExtName(getExtName(s.getAttachName()));
            req.setAttContext(commonService.fileToBase64(s.getAttachStorePath()));
            attachInfo.setAttachStorePath(uploadFile(req));
            s.setKlkPath(attachInfo.getAttachStorePath());
            return attachInfo;
        }).collect(Collectors.toList());
    }

    /**
     * 从文件名中获取后缀名
     *
     * @param attachName
     * @return
     */
    private String getExtName(String attachName) {
        return attachName.substring(attachName.lastIndexOf(".") + 1);
    }


    /**
     * 根据卡号查询卡BIN信息
     *
     * @param acctNo
     * @return
     */
    public Map<String, String> getCardBinMap(String acctNo) throws Exception {
        initUtil.doInit();
        V2MmsOpenApiCardBin cardBin = new V2MmsOpenApiCardBin();
        cardBin.setVersion(KlkConstant.VERSION);
        cardBin.setOrderNo(CommonUtil.getOrderNo());
        cardBin.setOrgCode(KlkConstant.ORG_CODE);
        cardBin.setCardNo(acctNo);
        String cardBinResponse = LKLSDK.httpPost(cardBin);
        JSONObject jsonObject = JSON.parseObject(cardBinResponse);
        if ("000000".equals(jsonObject.getString("retCode"))) {
            JSONObject respData = jsonObject.getJSONObject("respData");
            Map<String, String> cardBinMap = new HashMap<>();
            cardBinMap.put("acctOpenBankCode", respData.getString("bankCode"));
            cardBinMap.put("acctClearBankCode", respData.getString("clearingBankCode"));
            cardBinMap.put("bankName", respData.getString("bankName"));
            return cardBinMap;
        }
        throw new RuntimeException();
    }


    /**
     * 修改银行卡信息
     */
    public ResponseData updateBankCard(UpdateBankCardReq req, UserVo userVo) {
        try {
            initUtil.doInit();
            V2MmsModifyLedgerReceiverRequest request = new V2MmsModifyLedgerReceiverRequest();
            request.setVersion(KlkConstant.VERSION);
            request.setOrderNo(CommonUtil.getOrderNo());
            request.setOrgCode(KlkConstant.ORG_CODE);
            // 根据用户id查询卡拉卡账号
            request.setReceiverNo(getKlkAccByUserId(userVo.getUserId(), userVo.getUserType()));
            request.setReceiverName(req.getAcctName());
            request.setContactMobile(selectMobileByUserType(userVo));
            request.setAcctNo(req.getAcctNo());
            request.setAcctTypeCode(KlkConstant.ACC_TYPE);
            Map<String, String> cardBinMap = getCardBinMap(req.getAcctNo());
            request.setAcctOpenBankCode(cardBinMap.get("acctOpenBankCode"));
            request.setAcctOpenBankName(req.getAcctOpenBankName());
            request.setAcctClearBankCode(cardBinMap.get("acctClearBankCode"));
            request.setAttachList(getUpdateAttachList(req.getAttachList()));
            String response = LKLSDK.httpPost(request);
            JSONObject jsonObject = JSON.parseObject(response);
            if ("000000".equals(jsonObject.getString("retCode"))) {
                return ResponseData.success("修改银行卡信息成功！");
            } else {
                throw new RuntimeException(jsonObject.getString("retMsg"));
            }
        } catch (Exception e) {
            log.error("修改卡拉卡账号信息出现异常：{}", e.getMessage());
            throw new RuntimeException("失败原因：" + e.getMessage());
        }
    }

    /**
     * 将前端传递的附件信息转换为三方修改需要的参数
     *
     * @param attachList
     * @return
     */
    private List<V2MmsModifyLedgerReceiverRequest.AttachInfo> getUpdateAttachList(List<AddOrUpdateBankCardReq.Attach> attachList) {
        return attachList.stream().map(s -> {
            V2MmsModifyLedgerReceiverRequest.AttachInfo attachInfo = new V2MmsModifyLedgerReceiverRequest.AttachInfo();
            attachInfo.setAttachName(s.getAttachName());
            attachInfo.setAttachType(commonService.getAttType(s.getAttachType()));
            UploadFileReq req = new UploadFileReq();
            req.setAttType(attachInfo.getAttachType());
            req.setAttExtName(getExtName(s.getAttachName()));
            req.setAttContext(commonService.fileToBase64(s.getAttachStorePath()));
            attachInfo.setAttachStorePath(uploadFile(req));
            return attachInfo;
        }).collect(Collectors.toList());
    }

    /**
     * 根据用户id查询卡拉卡账号
     *
     * @param userId
     * @return
     */
    private String getKlkAccByUserId(Long userId, Integer userType) {
        return klkAccountMapper.selectOne(new LambdaUpdateWrapper<KlkAccount>()
                        .eq(KlkAccount::getDelFlag, PublicCommon.启用)
                        .eq(KlkAccount::getUserType, userType)
                        .eq(KlkAccount::getUserId, userId))
                .getReceiverNo();
    }

    /**
     * 查询开户行名称
     */
    @Override
    public ResponseData getBankName(GetBankNameReq req) {
        try {
            Map<String, String> cardBinMap = getCardBinMap(req.getCardNo());
            return ResponseData.success(cardBinMap.get("bankName"));
        } catch (Exception e) {
            log.error("查询开户行信息出现异常：{}", e.getMessage());
            return ResponseData.success();
        }
    }

    /**
     * 获取银行卡信息
     */
    @Override
    public ResponseData<GetBankInfoResp> getBankInfo(UserVo userVo) {
        KlkAccount klkAccount = klkAccountMapper.selectOne(new LambdaUpdateWrapper<KlkAccount>()
                .eq(KlkAccount::getDelFlag, PublicCommon.启用)
                .eq(KlkAccount::getUserType, userVo.getUserType())
                .eq(KlkAccount::getUserId, userVo.getUserId()));
        GetBankInfoResp getBankInfoResp = new GetBankInfoResp();
        if (klkAccount == null) {
            getBankInfoResp.setBindResult(-1);
        } else {
            getBankInfoResp.setId(klkAccount.getId());
            getBankInfoResp.setAcctName(klkAccount.getAcctName());
            getBankInfoResp.setAcctCertificateNo(klkAccount.getAcctCertificateNo());
            getBankInfoResp.setAcctNo(klkAccount.getAcctNo());
            getBankInfoResp.setAcctOpenBankName(klkAccount.getAcctOpenBankName());
            List<KlkAccountAttach> klkAccountAttachList = klkAccountAttachService.getBaseMapper().selectList(new LambdaUpdateWrapper<KlkAccountAttach>()
                    .eq(KlkAccountAttach::getDelFlag, PublicCommon.启用)
                    .eq(KlkAccountAttach::getLakalaAccountId, klkAccount.getId()));
            if (CollectionUtil.isNotEmpty(klkAccountAttachList)) {
                getBankInfoResp.setAttachList(klkAccountAttachList.stream().map(s -> {
                    GetBankInfoResp.Attach attach = new GetBankInfoResp.Attach();
                    attach.setAttachType(s.getAttachType());
                    attach.setAttachName(s.getAttachName());
                    attach.setAttachStorePath(s.getHttpPath());
                    return attach;
                }).collect(Collectors.toList()));
            }
            // resp.setBindResult(); 绑定结果：1-审核中 2-审核失败 3-审核成功 -1-未提交审核
            // klkAccount.getBindStatus() 绑定状态：1-未绑定 2-绑定中 3-已绑定 4-绑定失败
            if (klkAccount.getBindStatus() == 1) {
                getBankInfoResp.setBindResult(-1);
            } else if (klkAccount.getBindStatus() == 2) {
                getBankInfoResp.setBindResult(1);
            } else if (klkAccount.getBindStatus() == 3) {
                getBankInfoResp.setBindResult(3);
            } else if (klkAccount.getBindStatus() == 4) {
                getBankInfoResp.setBindResult(2);
                getBankInfoResp.setAuditFailReason(klkAccount.getBindFailReason());
            }
        }

        return ResponseData.success(getBankInfoResp);
    }

    @Autowired
    private KlkWithdrawalRecordMapper klkWithdrawalRecordMapper;

    /**
     * 提现
     */
    @Override
    public void withdrawal(WithdrawalRecord withdrawalRecord) {

        KlkWithdrawalRecord klkWithdrawalRecord = getKlkWithdrawalRecord(withdrawalRecord);

        // 调用三方接口进行分账
        klkWithdrawalRecord = divideAccount(klkWithdrawalRecord);


        klkWithdrawalRecordMapper.insert(klkWithdrawalRecord);

        if (StrUtil.isNotBlank(klkWithdrawalRecord.getBalanceSplitRemark())) {
            withdrawalRecordMapper.update(null, new LambdaUpdateWrapper<WithdrawalRecord>()
                    .eq(WithdrawalRecord::getId, klkWithdrawalRecord.getWithdrawalRecordId())
                    .set(WithdrawalRecord::getRefuseReason, klkWithdrawalRecord.getBalanceSplitRemark()));
        }
    }

    @Autowired
    private WithdrawalRecordMapper withdrawalRecordMapper;


    //商户号
    @Value("${lalkla.merchantNo}")
    private String merchantNo;

    /**
     * 分账
     *
     * @param klkWithdrawalRecord
     * @return
     */
    private KlkWithdrawalRecord divideAccount(KlkWithdrawalRecord klkWithdrawalRecord) {
        try {
            initUtil.doInit();
            V3SacsBalanceSeparateRequest request = new V3SacsBalanceSeparateRequest();
            request.setMerchantNo(merchantNo);
            request.setOutSeparateNo(getOutSeparateNo());
            request.setTotalAmt(klkWithdrawalRecord.getTotalAmt());
            request.setCalType("0"); //0- 按照指定金额，1- 按照指定比例。默认 0
            request.setRecvDatas(getRecvDatas(klkWithdrawalRecord));

            klkWithdrawalRecord.setOutSeparateNo(request.getOutSeparateNo());
            String response = LKLSDK.httpPost(request);
            JSONObject jsonObject = JSON.parseObject(response);
            if ("SACS0000".equals(jsonObject.getString("code"))) {
                JSONObject respData = jsonObject.getJSONObject("resp_data");
                klkWithdrawalRecord.setBalanceSplitStatus(getBalanceSplitStatus(respData.getString("status")));
            } else {
                throw new ServiceException(jsonObject.getString("msg"));
            }
            return klkWithdrawalRecord;
        } catch (Exception e) {
            log.error("分账出现异常：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 1-处理中 2-已受理 3-成功 4-失败
     *
     * @param status
     * @return
     */
    @Override
    public Integer getBalanceSplitStatus(String status) {
        switch (status) {
            case KlkConstant.PROCESSING:
                return 1;
            case KlkConstant.ACCEPTED:
                return 2;
            case KlkConstant.SUCCESS:
                return 3;
            case KlkConstant.FAIL:
                return 4;
            default:
                return -1;
        }
    }

    private List<V3SacsBalanceSeparateRequest.RecvData> getRecvDatas(KlkWithdrawalRecord klkWithdrawalRecord) {
        KlkAccount klkAccount = klkAccountMapper.selectOne(new LambdaUpdateWrapper<KlkAccount>()
                .eq(KlkAccount::getDelFlag, PublicCommon.启用)
                .eq(KlkAccount::getUserType, klkWithdrawalRecord.getUserType())
                .eq(KlkAccount::getUserId, klkWithdrawalRecord.getUserId()));
        V3SacsBalanceSeparateRequest.RecvData recvData = new V3SacsBalanceSeparateRequest.RecvData();
        recvData.setRecvNo(klkAccount.getReceiverNo());
        recvData.setSeparateValue(klkWithdrawalRecord.getTotalAmt());
        return Collections.singletonList(recvData);
    }

    private KlkWithdrawalRecord getKlkWithdrawalRecord(WithdrawalRecord withdrawalRecord) {
        KlkWithdrawalRecord klkWithdrawalRecord = new KlkWithdrawalRecord();
        klkWithdrawalRecord.setUserId(withdrawalRecord.getUserId());
        klkWithdrawalRecord.setUserType(withdrawalRecord.getUserType());
        klkWithdrawalRecord.setTotalAmt(transferTotalAmt(withdrawalRecord.getPrice()));
        klkWithdrawalRecord.setAcctNo(withdrawalRecord.getBankCard());
        klkWithdrawalRecord.setAcctOpenBankName(withdrawalRecord.getBank());
        klkWithdrawalRecord.setAcctName(withdrawalRecord.getFullName());
        klkWithdrawalRecord.setWithdrawalRecordId(withdrawalRecord.getId());
        return klkWithdrawalRecord;
    }

    /**
     * 将提现金额转换为分
     *
     * @param price
     * @return
     */
    private String transferTotalAmt(BigDecimal price) {
        return price.multiply(new BigDecimal("100")).intValue() + "";
    }

    /**
     * 获取分账指令流水号
     *
     * @return
     */
    private String getOutSeparateNo() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 查询银行卡是否绑定成功
     *
     * @param userVo
     * @return
     */
    @Override
    public ResponseData<SelectBindResultResp> selectBindResult(UserVo userVo) {
        SelectBindResultResp resp = new SelectBindResultResp();
        KlkAccount klkAccount = klkAccountMapper.selectOne(new LambdaQueryWrapper<KlkAccount>()
                .eq(KlkAccount::getDelFlag, PublicCommon.启用)
                .eq(KlkAccount::getUserType, userVo.getUserType())
                .eq(KlkAccount::getUserId, userVo.getUserId()));
        // resp.setBindResult(); 绑定结果：1-审核中 2-审核失败 3-审核成功 -1-未提交审核
        // klkAccount.getBindStatus() 绑定状态：1-未绑定 2-绑定中 3-已绑定 4-绑定失败
        if (klkAccount == null) {
            resp.setBindResult(-1);
        } else if (klkAccount.getBindStatus() == 2) {
            resp.setBindResult(1);
        } else if (klkAccount.getBindStatus() == 3) {
            resp.setBindResult(3);
        } else if (klkAccount.getBindStatus() == 4) {
            resp.setBindResult(2);
            resp.setAuditFailReason(klkAccount.getBindFailReason());
        }
        return ResponseData.success(resp);
    }
}
