package com.jeequan.jeepay.thirdparty.channel.ryxpay;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.resource.BytesResource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchModifyApplymentService;
import com.jeequan.jeepay.core.model.applyment.MchModifyApplymentModel;
import com.jeequan.jeepay.core.model.applyment.RyxpayApplymentInfo;
import com.jeequan.jeepay.core.model.params.ruipay.RyxpayIsvParams;
import com.jeequan.jeepay.core.utils.ImageUtils;
import com.jeequan.jeepay.service.impl.MchModifyApplymentService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.thirdparty.channel.ryxpay.model.ReqMethod;
import com.jeequan.jeepay.thirdparty.channel.ryxpay.model.RyxAccessResp;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.ByteArrayOutputStream;
import java.util.Objects;

@Slf4j
@Service
public class RyxpayMchModifyApplymentService implements IIsvmchModifyApplymentService {

    @Autowired
    protected SysConfigService sysConfigService;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private MchModifyApplymentService mchModifyApplymentService;

    @Autowired
    private MchInfoConverter mchInfoConverter;

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> localModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
        MchApplyment resultMchApplyment = new MchApplyment();

        MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
        resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
        resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
        MchApplyment mchApplyment = mchDataPair.getValue();
        resultMchApplyment.setApplyId(mchApplyment.getApplyId());

        String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
        MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);

        String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
        RyxpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, RyxpayApplymentInfo.class);
        resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));

        originMchModifyData.setMchShortName(mchModifyData.getMchShortName());
        resultMchApplyment.setMchShortName(mchModifyData.getMchShortName());

        return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> localModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
        MchApplyment resultMchApplyment = new MchApplyment();

        MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
        resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
        resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
        MchApplyment mchApplyment = mchDataPair.getValue();
        resultMchApplyment.setApplyId(mchApplyment.getApplyId());

        String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
        MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);

        String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
        RyxpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, RyxpayApplymentInfo.class);
        resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));

        originMchModifyData.setSettAccountType(mchModifyData.getSettAccountType());
        originMchModifyData.setAuthSettle(mchModifyData.getIllegal());
        originMchModifyData.setSettAccountLicenseImg(mchModifyData.getSettAccountLicenseImg());
        originMchModifyData.setSettAccountName(mchModifyData.getSettAccountName());
        originMchModifyData.setSettAccountNo(mchModifyData.getSettAccountNo());
        originMchModifyData.setSettAccountBankName(mchModifyData.getSettAccountBankName());
        originMchModifyData.setLetterOfAuthPic(mchModifyData.getNonLegSettleAuthPic());
        originMchModifyData.setSettAccountIdcardNo(mchModifyData.getSettAccountIdcardNo());
        originMchModifyData.setSettAccountIdcard1Img(mchModifyData.getSettAccountIdcard1Img());
        originMchModifyData.setSettAccountIdcard2Img(mchModifyData.getSettAccountIdcard2Img());
        originMchModifyData.setSettAccountIdcardEffectBegin(mchModifyData.getSettAccountIdcardEffectBegin());
        originMchModifyData.setSettAccountIdcardEffectEnd(mchModifyData.getSettAccountIdcardEffectEnd());

        return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> localModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        return mchDataPair;
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();

        MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
        resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
        resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
        MchApplyment mchApplyment = mchDataPair.getValue();

        RyxpayIsvParams isvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
        MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);

        JSONObject param = new JSONObject();
        param.put("accessId", isvParams.getAccessId());
        param.put("merInId", JSON.parseObject(mchApplyment.getSuccResParameter()).getString("merInId"));
        param.put("merName", mchModifyData.getMchShortName());

        try {
            RyxAccessResp ryxAccessResp = RyxpayKit.auditReqApi(ReqMethod.Method.MERCHANT_UPDATE_MERC_NAME, isvParams, param, null);

            if (RyxAccessResp.RESULT_OK.equals(ryxAccessResp.getCode())) {
                return localModifyBase(mchDataPair);
            } else {
                resultModifyApplyment.setApplyErrorInfo("[" + ryxAccessResp.getMsg() + "]");
                resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
            }

            String remark = "瑞银信基本信息变更已发起";
            resultModifyApplyment.setRemark(remark);
            log.debug("瑞银信基本信息变更发起成功");
        } catch (Exception e) {
            resultModifyApplyment.setApplyErrorInfo("[" + e.getMessage() + "]");
            resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
        }

        return new MutablePair<>(resultModifyApplyment, null);
    }

    public byte[] getFileBytes(String imgUrl, String picType) {
        Assert.notNull(imgUrl, "缺少类型为" + picType + "的图片");

        // 下载文件
        byte[] imgFileByteArray = null;
        try {
            ByteArrayOutputStream baos = ImageUtils.compressNetPic(imgUrl, 2048 * 1024);
            imgFileByteArray = baos.toByteArray();
        } catch (IORuntimeException e) {
            e.printStackTrace();
        }

        return imgFileByteArray;
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();

        MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
        resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
        resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
        MchApplyment mchApplyment = mchDataPair.getValue();

        RyxpayIsvParams isvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
        MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);

        JSONObject param = new JSONObject();
        JSONObject otherParam = new JSONObject();

        // 上传图片
        if ("B".equals(mchModifyData.getSettAccountType())) {
            param.put("settleType", "3");
            otherParam.put("cardPic", new BytesResource(getFileBytes(mchModifyData.getSettAccountLicenseImg(), "开户许可证")));
        } else {
            otherParam.put("cardPic", new BytesResource(getFileBytes(mchModifyData.getSettAccountLicenseImg(), "银行卡卡号面")));
        }

        if ("Y".equals(mchModifyData.getIllegal())) {
            param.put("settleType", "2");
            // 非法人结算, 上传身份证图片
            otherParam.put("autPic", new BytesResource(getFileBytes(mchModifyData.getNonLegSettleAuthPic(), "授权结算函")));
//            String settlePersonIdcardPositive = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, mchModifyData.getSettAccountIdcard1Img(), "07");
//            param.put("settlePersonIdcardPositive", settlePersonIdcardPositive);
//            String settlePersonIdcardOpposite = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, mchModifyData.getSettAccountIdcard2Img(), "08");
//            param.put("settlePersonIdcardOpposite", settlePersonIdcardOpposite);
//            String letterOfAuthPic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, mchModifyData.getNonLegSettleAuthPic(), "26");
//            param.put("letterOfAuthPic", letterOfAuthPic);
        } else {
            param.put("settleType", "1");
        }

        if (mchApplyment.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
            param.put("settleCredType", "0105");
            param.put("settleCredNo", mchModifyData.getSettAccountIdcardNo());
        }

        param.put("bankCard", mchModifyData.getSettAccountNo());
        param.put("headBankNo", mchModifyData.getBankCode());
        param.put("openBankChild", mchModifyData.getBankSubCode());
        String succResParameter = mchApplyment.getSuccResParameter();
        JSONObject succResJson = JSON.parseObject(succResParameter);
        param.put("merInId", succResJson.getString("merInId"));

        try {
            RyxAccessResp ryxAccessResp = RyxpayKit.auditReqApi(ReqMethod.Method.MERCHANT_UPDATE_SETTLE_CARD, isvParams, param, otherParam);

            if (RyxAccessResp.RESULT_OK.equals(ryxAccessResp.getCode())) {
                resultModifyApplyment.setChannelApplyNo(ryxAccessResp.getResult().getString("orderId"));
                resultModifyApplyment.setChannelVar1(ryxAccessResp.getResult().toJSONString());
                resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
            } else {
                String bizMsg = ryxAccessResp.getMsg();
                resultModifyApplyment.setApplyErrorInfo("[" + bizMsg + "]");
                resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);

                return new MutablePair<>(resultModifyApplyment, null);
            }

            String remark = "瑞银信结算信息变更已发起";
            resultModifyApplyment.setRemark(remark);
            log.debug("瑞银信结算信息变更发起成功");
        } catch (Exception e) {
            resultModifyApplyment.setApplyErrorInfo("[" + e.getMessage() + "]");
            resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);

            return new MutablePair<>(resultModifyApplyment, null);
        }

        return new MutablePair<>(resultModifyApplyment, null);
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        return mchDataPair;
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlementType(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        throw new BizException("当前通道不支持该操作");
    }

    @Override
    public MutablePair<MchModifyApplyment, MchApplyment> queryModifyResult(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();

        MchModifyApplyment modifyApplyment = mchDataPair.getLeft();
        resultModifyApplyment.setModifyApplyId(modifyApplyment.getModifyApplyId());

        MchApplyment mchApplyment = mchDataPair.getRight();

        RyxpayIsvParams isvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        JSONObject param = new JSONObject();
        String merInId = JSON.parseObject(mchApplyment.getSuccResParameter()).getString("merInId");
        param.put("merInId", merInId);
        param.put("flag", "1");

        RyxAccessResp ryxAccessResp  = RyxpayKit.auditReqApi(ReqMethod.Method.MERCHANT_UPDATE_SETTLE_CARD, isvParams, param, null);
        String bizMsg = ryxAccessResp.getMsg();
        String bizCode = ryxAccessResp.getCode();

        if (!RyxpayKit.AUDIT_SUCCESS_CODE.equals(bizCode)) {
            throw new BizException("查询变更结果失败, " + bizMsg);
        }

        JSONObject merchBase = ryxAccessResp.getResult().getJSONObject("merchBase");
        String merStatus = merchBase.getString("merStatus");
        String reason = merchBase.getString("finalAuditNoMemo");

        if (Objects.equals("00", merStatus)) {
            // 审核通过
            resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
            localModifySettlement(mchDataPair);
        }

        if (Objects.equals("32", merStatus)) {
            // 修改失败
            resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
            resultModifyApplyment.setRemark(reason);
            mchModifyApplymentService.updateById(mchInfoConverter.toDbEntity(resultModifyApplyment));
        }

        return mchDataPair;
    }
}
