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

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.entity.MchSubInfo;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
import com.jeequan.jeepay.core.model.applyment.SxfpayApplymentInfo;
import com.jeequan.jeepay.core.model.params.sxfpay.SxfpayIsvParams;
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
import com.jeequan.jeepay.service.impl.MchSubInfoService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service("sxfpayMchApplymentService")
public class SxfpayMchApplymentService implements IIsvmchApplymentService<SxfpayApplymentInfo> {

    @Autowired
    private SysConfigService sysConfigService;

    public static final String logPrefix = "【银盛商户进件】";

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private MchSubInfoService mchSubInfoService;

    public JSONObject getApplymentParams(MchApplyment mchApplyment) {
        SxfpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), SxfpayApplymentInfo.class);

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

        JSONObject resultParam = new JSONObject();
        if (!StrUtil.isEmpty(applymentInfo.getMerName())) {
            resultParam.put("merName", applymentInfo.getMerName());
        }
        resultParam.put("mecDisNm", applymentInfo.getMecDisNm());
        resultParam.put("mblNo", applymentInfo.getMblNo());
//        resultParam.put("operationalType", applymentInfo.getOperationalType());
        resultParam.put("operationalType", "01");
        resultParam.put("haveLicenseNo", applymentInfo.getHaveLicenseNo());
//        resultParam.put("mecTypeFlag", applymentInfo.getMecTypeFlag());
        resultParam.put("mecTypeFlag", "00");
        resultParam.put("cprRegAddr", applymentInfo.getCprRegAddr());
        resultParam.put("regProvCd", applymentInfo.getRegProvCd());
        resultParam.put("regCityCd", applymentInfo.getRegCityCd());
        resultParam.put("regDistCd", applymentInfo.getRegDistCd());
        resultParam.put("mccCd", applymentInfo.getMccCd());
        resultParam.put("csTelNo", applymentInfo.getCsTelNo());

        List<SxfpayApplymentInfo.RateInfo> rateInfos = applymentInfo.collQrCodeList();
        resultParam.put("qrcodeList", rateInfos);

//        resultParam.put("specifyWechatChannel", )
//        resultParam.put("specifyALiPayChannel", )

        resultParam.put("callbackUrl", sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/mchApplyment/notify/" + mchApplyment.getIfCode() + "/" + mchApplyment.getApplyId());

        if (applymentInfo.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
            resultParam.put("cprRegNmCn", applymentInfo.getCprRegNmCn());
            resultParam.put("registCode", applymentInfo.getRegistCode());

            if (MchApplyment.MERCHANT_TYPE_ENTERPRISE == applymentInfo.getMerchantType()) {
                resultParam.put("licenseMatch", applymentInfo.getLicenseMatch());
            }

            resultParam.put("businessLicStt", applymentInfo.getBusinessLicStt());
            resultParam.put("businessLicEnt", applymentInfo.getBusinessLicEnt());
        }

        resultParam.put("identityName", applymentInfo.getIdentityName());
        resultParam.put("identityTyp", ObjUtil.defaultIfNull(applymentInfo.getIdentityTyp(), "00"));
        resultParam.put("identityNo", applymentInfo.getIdentityNo());
        resultParam.put("legalPersonLicStt", applymentInfo.getLegalPersonLicStt());
        resultParam.put("legalPersonLicEnt", applymentInfo.getLegalPersonLicEnt());

        resultParam.put("actNo", applymentInfo.getActNo());
        resultParam.put("lbnkNo", applymentInfo.getLbnkNo());

        resultParam.put("actNm", applymentInfo.getActNm());
        resultParam.put("actTyp", applymentInfo.getActTyp());

        // 对私结算
        if ("01".equals(applymentInfo.getActTyp())) {
            resultParam.put("actNoType", ObjUtil.defaultIfNull(applymentInfo.getActNoType(), "00"));
            resultParam.put("stmManIdNo", applymentInfo.getStmManIdNo());
            resultParam.put("accountLicStt", applymentInfo.getAccountLicStt());
            resultParam.put("accountLicEnt", applymentInfo.getAccountLicEnt());
        }

        // 上传图片
        if (applymentInfo.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
            String licensePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getLicensePic(), "13");
            resultParam.put("licensePic", licensePic);
        }

        String legalPersonidPositivePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getLegalPersonidPositivePic(), "02");
        resultParam.put("legalPersonidPositivePic", legalPersonidPositivePic);

        String legalPersonidOppositePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getLegalPersonidOppositePic(), "03");
        resultParam.put("legalPersonidOppositePic", legalPersonidOppositePic);

        if ("00".equals(applymentInfo.getActTyp())) {
            String openingAccountLicensePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getOpeningAccountLicensePic(), "04");
            resultParam.put("openingAccountLicensePic", openingAccountLicensePic);
        } else {
            String bankCardPositivePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getBankCardPositivePic(), "05");
            resultParam.put("bankCardPositivePic", bankCardPositivePic);
        }

        if ("Y".equals(applymentInfo.getAuthSettle())) {
            String settlePersonIdcardPositive = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getSettlePersonIdcardPositive(), "07");
            resultParam.put("settlePersonIdcardPositive", settlePersonIdcardPositive);

            String settlePersonIdcardOpposite = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getSettlePersonIdcardOpposite(), "08");
            resultParam.put("settlePersonIdcardOpposite", settlePersonIdcardOpposite);

            String letterOfAuthPic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getLetterOfAuthPic(), "26");
            resultParam.put("letterOfAuthPic", letterOfAuthPic);
        }

        String storePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getStorePic(), "10");
        resultParam.put("storePic", storePic);

        String insideScenePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getInsideScenePic(), "11");
        resultParam.put("insideScenePic", insideScenePic);

        String businessPlacePic = SxfpayKit.reqUpload(ReqMethod.Method.MERCHANT_INCOME_PHOTO_UPLOAD, isvParams, applymentInfo.getBusinessPlacePic(), "12");
        resultParam.put("businessPlacePic", businessPlacePic);

        return resultParam;
    }

    @Override
    public MchApplyment rejectModify(MchApplyment mchApplyment) {
        return firstApplyment(mchApplyment);
    }

    @Override
    public MchApplyment replenishInfo(MchApplyment mchApplyment) {
        return null;
    }

    @Override
    public MchApplyment query(MchApplyment mchApplyment) {
        String logPrefix = "【随行付商户进件状态查询】";
        MchApplyment result = new MchApplyment();
        result.setState(mchApplyment.getState());
        result.setApplyId(mchApplyment.getApplyId());

        if (mchApplyment.getState() == com.jeequan.jeepay.core.entity.MchApplyment.STATE_AUDITING) {
            // 资料确认状态查询
            // 获取支付参数
            SxfpayIsvParams isvParams = (SxfpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
            JSONObject bizContent = new JSONObject();
            // 请求参数
            bizContent.put("applicationId", mchApplyment.getChannelApplyNo());

            // 解密后数据
            JSONObject resData = SxfpayKit.reqApi(ReqMethod.Method.MERCHANT_APPLY_QUERY, isvParams, bizContent);

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

            if (!SxfpayKit.SUCCESS_CODE.equals(bizCode)) {
                result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
                result.setChannelVar1(resData.toJSONString());
                result.setApplyErrorInfo("[" + bizMsg + "]");
                return mchApplyment;
            }

            result.setApplyErrorInfo(bizCode + "[" + suggestion + "]");
            log.error("{} 请求失败：code={}, msg={}", logPrefix, bizCode, suggestion);

            // 审核成功
            if ("1".equals(taskStatus)) {
                result.setChannelMchNo(mno);
                result.setSuccResParameter(resData.toString());
                subMchColl(result, resData.getJSONArray("repoInfo"));
            }

            // 审核拒绝
            else if ("2".equals(taskStatus)) {
                result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_REJECT_WAIT_MODIFY);
                result.setApplyErrorInfo("[" + suggestion + "]");
                return result;

            } else {
                result.setApplyErrorInfo("[" + suggestion + "]");
                return result;
            }
        }

        return result;
    }

    @Override
    public ApplymentSignInfo signInfo(MchApplyment mchApplyment) {
        return null;
    }

    @Override
    public void subMchColl(MchApplyment mchApplyment, Object callback) {
        JSONArray repoInfo = (JSONArray) callback;
        for (int i = 0; i < repoInfo.size(); i++) {
            JSONObject repo = repoInfo.getJSONObject(i);
            MchSubInfoEntity subInfo = new MchSubInfoEntity();
            subInfo.setSubMchType(repo.getString("childNoType"));
            subInfo.setSubMchId(repo.getString("childNo"));
            subInfo.setChannelId(repo.getString("channelId"));
            subInfo.setRemark(repo.getString("errMessage"));
            subInfo.setChannelMchNo(mchApplyment.getChannelMchNo());
            subInfo.setSubMchWay("SXF");
            subInfo.setStatus(repo.getString("repoStatus"));
            subInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
            subInfo.setExt(repo);
            subInfo.setMainUse(1);
            subInfo.setMchApplyId(mchApplyment.getApplyId());
            try {
                mchSubInfoService.save(subInfo);
            } catch (DuplicateKeyException e) {
                log.info("重复子商户数据，不做处理");
            }
        }
    }

    /**
     * 重新子商户信息收集方法
     * @param mchApplyment
     */
    @Override
    public void subMchColl(MchApplyment mchApplyment) {
        SxfpayIsvParams isvParams = (SxfpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
        JSONObject bizContent = new JSONObject();
        bizContent.put("mno",mchApplyment.getChannelMchNo());
        JSONObject response = SxfpayKit.reqApi(ReqMethod.Method.MERCHANT_INFO_QUERY, isvParams, bizContent);
        JSONArray repoInfo = response.getJSONArray("repoInfo");
        repoInfo.stream().map(item -> (JSONObject)item).forEach(repo -> {
            MchSubInfoEntity item = new MchSubInfoEntity();
            item.setChannelMchNo(mchApplyment.getChannelMchNo());
            item.setSubMchType(repo.getString("childNoType"));
            item.setSubMchId(repo.getString("childNo"));
            item.setStatus(repo.getString("repoStatus"));
            item.setChannelId(repo.getString("channelId"));
            item.setRemark(repo.getString("errMessage"));
            item.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
            // TODO 随行付没有银联和网联的标识
            item.setSubMchWay("SXF");
            item.setMainUse(1);
            item.setExt(((JSONObject) JSON.toJSON(repo)));
            item.setMchApplyId(mchApplyment.getApplyId());
            try {
                mchSubInfoService.save(item);
            }catch (DuplicateKeyException e){
            }
        });
    }
}
