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

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.resource.BytesResource;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.entity.MchSubInfo;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
import com.jeequan.jeepay.core.model.applyment.RyxpayApplymentInfo;
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
import com.jeequan.jeepay.core.model.params.ruipay.RyxpayIsvParams;
import com.jeequan.jeepay.core.utils.ImageUtils;
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.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.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service("ryxpayMchApplymentService")
public class RyxpayMchApplymentService implements IIsvmchApplymentService<RyxpayApplymentInfo> {

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private MchSubInfoService mchSubInfoService;

    @Autowired
    private SysConfigService sysConfigService;

    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;
    }

    public JSONObject getApplymentParams(MchApplyment mchApplyment) {
        JSONObject result = new JSONObject();
        List<BytesResource> files = new ArrayList<>();
        result.put("files", files);
        RyxpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), RyxpayApplymentInfo.class);

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

        result.put("accessMode", "1");
        result.put("orgId", isvParams.getOrgId());
        result.put("merProp", applymentInfo.getMerProp());

        files.add(new BytesResource(getFileBytes(applymentInfo.getStoreOuterImg(), "门头照"), "pic0211.jpg"));
        files.add(new BytesResource(getFileBytes(applymentInfo.getStoreInnerImg(), "门店内景照"), "pic0117.jpg"));
        files.add(new BytesResource(getFileBytes(applymentInfo.getStoreCashierImg(), "收银台照"), "pic0217.jpg"));

        if (!"7".equals(result.getString("merProp"))) {
            result.put("merName", applymentInfo.getMerName());
            result.put("orgMerName", applymentInfo.getOrgMerName());

        }

        result.put("merNameAbbr", applymentInfo.getMerNameAbbr());
        result.put("merchRelp", ObjUtil.defaultIfNull(applymentInfo.getMerchRelp(), "00"));

        if (!"7".equals(result.getString("merProp"))) {
            files.add(new BytesResource(getFileBytes(applymentInfo.getLicenseImg(), "营业执照"), "pic0103.jpg"));
            files.add(new BytesResource(getFileBytes(applymentInfo.getIdcard1Img(), "法人身份证人像面"), "pic0111.jpg"));
            files.add(new BytesResource(getFileBytes(applymentInfo.getIdcard2Img(), "法人身份证国徽面"), "pic0112.jpg"));
            result.put("licType", "1");
            result.put("licNum", applymentInfo.getLicNum());
            result.put("licNumStartTime", applymentInfo.getLicNumStartTime());
            result.put("licNumTime", applymentInfo.getLicNumTime());
            result.put("credPeople", applymentInfo.getCredPeople());
            result.put("credType", applymentInfo.getCredType());
            result.put("credNo", applymentInfo.getCredNo());
            result.put("credStartTime", applymentInfo.getCredStartTime());
            result.put("credTime", applymentInfo.getCredTime());
            result.put("credAddr", applymentInfo.getIdcardAddress());

            if ("Y".equals(applymentInfo.getAuthSettle())) {
                files.add(new BytesResource(getFileBytes(applymentInfo.getSettAccountIdcard1Img(), "结算人身份证人像面"), "pic0119.jpg"));
                files.add(new BytesResource(getFileBytes(applymentInfo.getSettAccountIdcard2Img(), "结算人身份证国徽面"), "pic0120.jpg"));
                files.add(new BytesResource(getFileBytes(applymentInfo.getLetterOfAuthPic(), "非法人结算授权函"), "pic0205.jpg"));
            }
        } else {
            result.put("microBizType", applymentInfo.getMicroBizType());

            // 小微
            files.add(new BytesResource(getFileBytes(applymentInfo.getStoreInnerImg(), "门店内景照"), "pic0118.jpg"));

            files.add(new BytesResource(getFileBytes(applymentInfo.getIdcard1Img(), "经营者身份证人像面"), "pic0119.jpg"));
            files.add(new BytesResource(getFileBytes(applymentInfo.getIdcard2Img(), "经营者身份证国徽面"), "pic0120.jpg"));
            files.add(new BytesResource(getFileBytes(applymentInfo.getIdcardInHandImg(), "经营者手持身份证照"), "pic0105.jpg"));
        }

        if ("3".equals(applymentInfo.getSettleType())) {
            // 对公
            files.add(new BytesResource(getFileBytes(applymentInfo.getSettAccountLicenseImg(), "开户许可证"), "pic0109.jpg"));
        } else {
            files.add(new BytesResource(getFileBytes(applymentInfo.getSettAccountLicenseImg(), "银行卡卡号面"), "pic0206.jpg"));
        }

        result.put("cityArea", applymentInfo.getCityArea());
        result.put("longitude", applymentInfo.getLongitude());
        result.put("latitude", applymentInfo.getLatitude());
        result.put("operateProvince", applymentInfo.getOperateProvince());
        result.put("operateCity", applymentInfo.getOperateCity());
        result.put("operateArea", applymentInfo.getOperateArea());
        result.put("contactPerson", applymentInfo.getContactPerson());
        result.put("contactPhone", applymentInfo.getContactPhone());
        result.put("operateAddr", applymentInfo.getOperateAddr());
        result.put("regAddr", applymentInfo.getRegAddr());
        result.put("manaScop", applymentInfo.getManaScop());
        result.put("mcc", applymentInfo.getMcc());

        result.put("bankCard", applymentInfo.getBankCard());
        result.put("accountProp", applymentInfo.getAccountProp());
        result.put("settleType", applymentInfo.getSettleType());
        result.put("bankCardName", applymentInfo.getBankCardName());
        result.put("settleCredType", applymentInfo.getSettleCredType());
        result.put("settleCredNo", applymentInfo.getSettleCredNo());
        result.put("settleCredStartTime", applymentInfo.getSettleCredStartTime());
        result.put("settleCredTime", applymentInfo.getSettleCredTime());
        result.put("bankCityArea", applymentInfo.getBankCityArea());
        result.put("headBankNo", applymentInfo.getHeadBankNo());
//        result.put("openBankName", applymentInfo.getOpenBankName());
        result.put("openBankChild", applymentInfo.getOpenBankChild());

        result.put("modelType", "2");
        result.put("debitRate", "2");
        result.put("pactType", "1");

        applymentInfo.collRateInfo(result);
        result.put("termNum", "1");
        result.put("serviceType", applymentInfo.getServiceType());
        result.put("tradeTypeReimburse", ObjUtil.defaultIfNull(applymentInfo.getTradeTypeReimburse(), "0"));
        result.put("certificationType", ObjUtil.defaultIfNull(applymentInfo.getCertificationType(), "1"));
        result.put("alipayCertificationType", ObjUtil.defaultIfNull(applymentInfo.getAlipayCertificationType(), "1"));
        result.put("regAddress", applymentInfo.getOperateAddr());
        result.put("contactSameToLegal", applymentInfo.getContactSameToLegal());
        result.put("contactCredType", ObjUtil.defaultIfNull(applymentInfo.getContactCredType(), "0105"));
        result.put("contactStartTime", applymentInfo.getContactStartTime());
        result.put("contactTime", applymentInfo.getContactTime());
        result.put("contactPersonCred", applymentInfo.getContactPersonCred());
        files.add(new BytesResource(getFileBytes(applymentInfo.getContactCardImg1(), "联系人身份证卡号面"), "pic0311.jpg"));
        files.add(new BytesResource(getFileBytes(applymentInfo.getContactCardImg2(), "联系人身份证国徽面"), "pic0312.jpg"));
        result.put("ifbenefit", "0");

        // 微信配置
        WxpayOauth2Params wxpayOauth2Params = (WxpayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.WXPAY);
        if (wxpayOauth2Params == null) {
            throw new BizException("服务商未配置微信oauth信息");
        }
        String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
        String subAppId = "";
        if (!ObjUtil.isEmpty(wxpayOauth2Params.getAppId())) {
            subAppId = wxpayOauth2Params.getAppId();
        }

        if (!ObjUtil.isEmpty(wxpayOauth2Params.getLiteAppId())) {
            subAppId = subAppId + "," + wxpayOauth2Params.getLiteAppId();
        }

        if (ObjUtil.isEmpty(subAppId)) {
            throw new BizException("服务商未配置微信oauth信息");
        }

        result.put("subAppid", subAppId);
        result.put("jsapiPath", paySiteUrl + "/");

        return result;
    }

    @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() == MchApplyment.STATE_AUDITING
                || mchApplyment.getState() == MchApplyment.STATE_WAIT_SIGN) {
            // 资料确认状态查询
            // 获取支付参数
            RyxpayIsvParams isvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
            JSONObject bizContent = new JSONObject();
            // 请求参数
            bizContent.put("orderId", mchApplyment.getChannelApplyNo());

            // 解密后数据
            RyxAccessResp resData = RyxpayKit.auditReqApi(ReqMethod.Method.MERCHANT_INCOME_RESULT, isvParams, bizContent, null);

            String bizMsg = resData.getMsg();
            String bizCode = resData.getCode();

            if (!RyxpayKit.AUDIT_SUCCESS_CODE.equals(bizCode)) {
                result.setApplyErrorInfo(bizCode + "[" + bizMsg + "]");
                result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_REJECT_WAIT_MODIFY);
                mchApplyment.setChannelVar1(resData.getResult().toJSONString());
                return mchApplyment;
            }

            String taskStatus = resData.getResult().getString("status");
            String suggestion = resData.getResult().getString("memo");

            String onlMerId = resData.getResult().getString("onlMerId");
            result.setSuccResParameter(resData.getResult().toJSONString());
            result.setApplyErrorInfo(bizCode + "[" + suggestion + "]");
            log.error("{} 请求失败：code={}, msg={}", logPrefix, bizCode, suggestion);


            // 审核成功
            if ("3".equals(taskStatus)) {
                result.setChannelMchNo(onlMerId);
                result.setState(MchApplyment.STATE_SUCCESS);
                result.setChannelVar1(resData.getResult().toString());
                subMchColl(result, resData.getResult());
            }
            // 待签约
            else if ("5".equals(taskStatus)) {
                String merInId = resData.getResult().getString("merInId");

                // 待签约
                RyxpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), RyxpayApplymentInfo.class);

                String merName;
                if (MchApplyment.MERCHANT_TYPE_PERSONAL == mchApplyment.getMerchantType()) {
                    merName = "商户" + applymentInfo.getIdcardName();
                } else {
                    merName = applymentInfo.getMchFullName();
                }

                try {
                    merName = URLEncoder.encode(merName, "UTF-8");
                } catch (UnsupportedEncodingException ignored) {
                }

                String urlTemplate = "https://rjp.ruiyinxin.com/mims2/ruijiaSign/index.html?merInId=%s&merName=%s";
                String url = String.format(urlTemplate, merInId, merName);
                JSONObject channelVar2 = new JSONObject();
                channelVar2.put("signUrl", url);
                result.setChannelVar2(channelVar2.toJSONString());
                result.setState(MchApplyment.STATE_WAIT_SIGN);
                return result;
            } else if ("1".equals(taskStatus)) {
                // 审核中
            } else {
                result.setApplyErrorInfo("[" + suggestion + "]");
                result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
                return result;
            }
        }

        return result;
    }

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

    @Override
    public void subMchColl(MchApplyment mchApplyment, Object callback) {
        JSONObject auditResult = (JSONObject) callback;
        if (auditResult.getString("wxMerId") != null) {
            try {
                // 保存微信子商户信息
                MchSubInfoEntity mchSubInfo = new MchSubInfoEntity();
                mchSubInfo.setChannelMchNo(mchApplyment.getChannelMchNo());
                mchSubInfo.setMchApplyId(mchApplyment.getApplyId());
                mchSubInfo.setSubMchType("WX");
                mchSubInfo.setStatus(auditResult.getString("wxStatus"));
                mchSubInfo.setMainUse(1);
                mchSubInfo.setRemark(auditResult.getString("wxResult"));
                mchSubInfo.setSubMchId(auditResult.getString("wxMerId"));
                mchSubInfo.setSubMchWay("RYX");
                mchSubInfo.setExt(auditResult);
                mchSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
                mchSubInfoService.save(mchSubInfo);
            } catch (DuplicateKeyException e) {
                log.warn("相同的微信子商户号, 不需要重复保存");
            } catch (Exception e) {
                e.printStackTrace();
                log.warn("保存微信子商户号错误");
            }
        }

        if (auditResult.getString("zfbMerId") != null) {
            try {
                // 保存支付宝子商户信息
                MchSubInfoEntity mchSubInfo = new MchSubInfoEntity();
                mchSubInfo.setChannelMchNo(mchApplyment.getChannelMchNo());
                mchSubInfo.setMchApplyId(mchApplyment.getApplyId());
                mchSubInfo.setSubMchType("ZFB");
                mchSubInfo.setStatus(auditResult.getString("zfbStatus"));
                mchSubInfo.setMainUse(1);
                mchSubInfo.setRemark(auditResult.getString("zfbResult"));
                mchSubInfo.setSubMchId(auditResult.getString("zfbMerId"));
                mchSubInfo.setSubMchWay("RYX");
                mchSubInfo.setExt(auditResult);
                mchSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
                mchSubInfoService.save(mchSubInfo);
            } catch (DuplicateKeyException e) {
                log.warn("相同的支付宝子商户号, 不需要重复保存");
            } catch (Exception e) {
                e.printStackTrace();
                log.warn("保存支付宝子商户号错误");
            }
        }
    }

    @Override
    public void subMchColl(MchApplyment mchApplyment) {
        RyxpayIsvParams ryxpayIsvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        JSONObject param = new JSONObject();
        param.put("orderId", mchApplyment.getChannelApplyNo());

        RyxAccessResp ryxAccessResp = RyxpayKit.auditReqApi(ReqMethod.Method.MERCHANT_INCOME_RESULT, ryxpayIsvParams, param, null);

        if (!RyxpayKit.AUDIT_SUCCESS_CODE.equals(ryxAccessResp.getCode())) {
            throw new BizException("瑞银信查询商户进件结果失败, " + ryxAccessResp.getMsg());
        }

        subMchColl(mchApplyment, ryxAccessResp.getResult());
    }
}
