package com.jeequan.jeepay.pay.ctrl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.entity.MchApp;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.IConfigContextQueryService;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.rqrs.AbstractMchAppRQ;
import com.jeequan.jeepay.core.model.rqrs.AbstractRQ;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.JeepayRSA2Kit;
import com.jeequan.jeepay.pay.service.ValidateService;
import com.jeequan.jeepay.service.impl.MchConfigService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/*
* api 抽象接口， 公共函数
*
* @author terrfly
*
* @date 2021/6/8 17:28
*/
public abstract class ApiController extends AbstractCtrl {

    @Autowired private ValidateService validateService;
    @Autowired private IConfigContextQueryService configContextQueryService;
    @Autowired private MchConfigService mchConfigService;


    /** 获取请求参数并转换为对象，通用验证  **/
    protected <T extends AbstractRQ> T getRQ(Class<T> cls){

        T bizRQ = getObject(cls);

        // [1]. 验证通用字段规则
        validateService.validate(bizRQ);

        return bizRQ;
    }


    /** 获取请求参数并转换为对象，商户通用验证  **/
    protected <T extends AbstractRQ> T getRQByWithMchSign(Class<T> cls){

        //获取请求RQ, and 通用验证
        T bizRQ = getRQ(cls);

        AbstractMchAppRQ abstractMchAppRQ = (AbstractMchAppRQ)bizRQ;

        //业务校验， 包括： 验签， 商户状态是否可用， 是否支持该支付方式下单等。
        String mchNo = abstractMchAppRQ.getMchNo();
        String appId = abstractMchAppRQ.getAppId();
        String sign = bizRQ.getSign();

        if(StringUtils.isAnyBlank(mchNo, appId, sign)){
            throw new BizException("参数有误！");
        }

        // pas非空：   验证通信秘钥
        if(StringUtils.isNotEmpty(abstractMchAppRQ.getPas())){
            if(!abstractMchAppRQ.getPas().equals(SysConfigService.PLATFORM_API_SECRET)){
                throw new BizException("通信秘钥错误！");
            }
        }else{ // pas是空的，说明商户自调用：  检查是否有接口权限

            if(!mchConfigService.queryMchHasApiEnt(mchNo, abstractMchAppRQ.apiName())){
                throw new BizException("商户无此接口["+abstractMchAppRQ.apiName()+"]权限！");
            }
        }

        MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(mchNo, appId);

        if(mchAppConfigContext == null){
            throw new BizException("商户或商户应用不存在");
        }

        if(mchAppConfigContext.getMchInfo() == null || mchAppConfigContext.getMchInfo().getState() != CS.YES){
            throw new BizException("商户信息不存在或商户状态不可用");
        }

        MchApp mchApp = mchAppConfigContext.getMchApp();
        if(mchApp == null || mchApp.getState() != CS.YES){
            throw new BizException("商户应用不存在或应用状态不可用");
        }

        if(!mchApp.getMchNo().equals(mchNo)){
            throw new BizException("参数appId与商户号不匹配");
        }

        if(StringUtils.isEmpty(mchApp.getAppSignType())){
            throw new BizException("商户未配置签名方式");
        }

        List<String> appSignType = JSONArray.parseArray(mchApp.getAppSignType(), String.class);
        if(!appSignType.contains(abstractMchAppRQ.getSignType().toUpperCase())){
            throw new BizException("商户不支持["+abstractMchAppRQ.getSignType()+"]签名方式");
        }

        // 转换为 JSON
        JSONObject bizReqJSON = (JSONObject)JSONObject.toJSON(bizRQ);
        bizReqJSON.remove("sign");

        // 验签
        if(MchApp.SIGN_TYPE_MD5.equalsIgnoreCase(abstractMchAppRQ.getSignType())){
            String appSecret = mchApp.getAppSecret();

            if(!sign.equalsIgnoreCase(JeepayKit.getSign(bizReqJSON, appSecret))){
                throw new BizException("验签失败");
            }

        }else if(MchApp.SIGN_TYPE_RSA2.equalsIgnoreCase(abstractMchAppRQ.getSignType())){
            String appRsa2PublicKey = mchApp.getAppRsa2PublicKey();
            try {
                if(!JeepayRSA2Kit.verify(bizReqJSON, appRsa2PublicKey, abstractMchAppRQ.getSign())){
                    throw new BizException("验签失败");
                }
            } catch (Exception e) {
                throw new BizException("验签异常");
            }
        }else{
            throw new BizException("不支持的签名方式");
        }

        return bizRQ;
    }
}
