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

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.SxfpayApplymentInfo;
import com.jeequan.jeepay.core.model.params.sxfpay.SxfpayIsvParams;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.thirdparty.channel.sxfpay.model.ReqMethod;
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;

@Slf4j
@Service
public class SxfpayMchModifyApplymentService implements IIsvmchModifyApplymentService {

    @Autowired
    protected SysConfigService sysConfigService;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @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();
        SxfpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, SxfpayApplymentInfo.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();
        SxfpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, SxfpayApplymentInfo.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();

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

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

        JSONObject param = new JSONObject();
        param.put("updateCallBackUrl", getCallbackUrl(mchApplyment.getIfCode(), mchApplyment.getApplyId()));
        param.put("mno", mchApplyment.getChannelMchNo());
        param.put("mecDisNm", mchModifyData.getMchShortName());

        try {
            JSONObject applyRespData = SxfpayKit.reqApi(ReqMethod.Method.MERCHANT_INFO_MODIFY, isvParams, param);

            String applicationId = applyRespData.getString("applicationId");
            String bizCode = applyRespData.getString("bizCode");

            if (SxfpayKit.SUCCESS_CODE.equals(bizCode)) {
                resultModifyApplyment.setChannelApplyNo(applicationId);
                resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
                resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
            } else {
                String bizMsg = applyRespData.getString("bizMsg");
                resultModifyApplyment.setChannelApplyNo(applicationId);
                resultModifyApplyment.setApplyErrorInfo("[" + bizMsg + "]");
                resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
                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);
    }

    @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();

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

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

        JSONObject param = new JSONObject();

        // 上传图片
        if ("B".equals(mchModifyData.getSettAccountType())) {
            String openingAccountLicensePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, mchModifyData.getSettAccountLicenseImg(), "04");
            param.put("openingAccountLicensePic", openingAccountLicensePic);
        } else {
            String bankCardPositivePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, mchModifyData.getSettAccountLicenseImg(), "05");
            param.put("bankCardPositivePic", bankCardPositivePic);
        }

        if ("Y".equals(mchModifyData.getIllegal())) {
            // 非法人结算, 上传身份证图片
            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);
        }

        param.put("updateCallBackUrl", getCallbackUrl(mchApplyment.getIfCode(), mchApplyment.getApplyId()));
        param.put("actNo", mchModifyData.getSettAccountNo());
        param.put("actTyp", mchModifyData.getSettAccountType().equals("B")? "00": "01");
        param.put("actNoType", "00");
        param.put("stmManIdNo", mchModifyData.getSettAccountIdcardNo());
        param.put("actNm", mchModifyData.getSettAccountName());
        param.put("lbnkNo", mchModifyData.getBankSubCode());
        param.put("mno", mchApplyment.getChannelMchNo());

        try {
            JSONObject applyRespData = SxfpayKit.reqApi(ReqMethod.Method.MERCHANT_INFO_MODIFY, isvParams, param);;

            String applicationId = applyRespData.getString("applicationId");
            String bizCode = applyRespData.getString("bizCode");

            if (SxfpayKit.SUCCESS_CODE.equals(bizCode)) {
                resultModifyApplyment.setChannelApplyNo(applicationId);
                resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
                resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
            } else {
                String bizMsg = applyRespData.getString("bizMsg");
                resultModifyApplyment.setChannelApplyNo(applicationId);
                resultModifyApplyment.setApplyErrorInfo("[" + bizMsg + "]");
                resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
                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();

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

        JSONObject param = new JSONObject();
        param.put("applicationId", modifyApplyment.getModifyApplyId());

        JSONObject bizData  = SxfpayKit.reqApi(ReqMethod.Method.MERCHANT_AUDIT_RESULT_QUERY, isvParams, param);
        String status = bizData.getString("status");
        String bizCode = bizData.getString("bizCode");

        if (!SxfpayKit.SUCCESS_CODE.equals(bizCode)) {
            throw new BizException("查询变更结果失败");
        }

        String bizMsg = bizData.getString("bizMsg");
        String suggestion = bizData.getString("suggestion");
        String mno = bizData.getString("mno");
        String taskStatus = bizData.getString("taskStatus");

        switch (taskStatus) {
            case "5":
                // 成功
                resultModifyApplyment.setChannelVar1(processChannelValue(modifyApplyment.getChannelVar1(), bizData));
                return handleSuccessCase(modifyApplyment, mchDataPair);
            case "4":
                // 待审核
                break;
            default:
                // 失败
                resultModifyApplyment.setChannelVar1(processChannelValue(modifyApplyment.getChannelVar1(), bizData));
                resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
                resultModifyApplyment.setApplyErrorInfo("[" + suggestion + "]");

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

        return mchDataPair;
    }

    private MutablePair<MchModifyApplyment, MchApplyment> handleSuccessCase(MchModifyApplyment modifyApplyment, MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
        switch (modifyApplyment.getModifyApplyType()) {
            case MchModifyApplyment.MODIFY_TYPE_BASE:
                return localModifyBase(mchDataPair);
            case MchModifyApplyment.MODIFY_TYPE_SETTLEMENT:
                return localModifySettlement(mchDataPair);
            default:
                return mchDataPair;
        }
    }

    private String processChannelValue(String channelVal, JSONObject bizData) {
        JSONObject channelValJSON = StrUtil.isEmptyIfStr(channelVal) ? new JSONObject() : JSON.parseObject(channelVal);
        channelValJSON.putAll(bizData);
        return channelValJSON.toJSONString();
    }

    private String getCallbackUrl(String ifCode, String applyId) {
        return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/mchApplyment/notify/" + ifCode + "/" + applyId;
    }
}
