package com.jeequan.jeepay.thirdparty.service;

import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.IsvInfo;
import com.jeequan.jeepay.core.entity.MchApp;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.interfaces.IConfigContextService;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.context.MchInfoConfigContext;
import com.jeequan.jeepay.core.model.oauth2.AlipayOauth2Params;
import com.jeequan.jeepay.core.model.oauth2.Oauth2Params;
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
import com.jeequan.jeepay.core.model.params.IsvParams;
import com.jeequan.jeepay.core.model.params.IsvsubMchParams;
import com.jeequan.jeepay.core.model.params.NormalMchParams;
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
import com.jeequan.jeepay.core.model.params.alipay.AlipayNormalMchParams;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayIsvParams;
import com.jeequan.jeepay.core.model.params.wxpay.WxpayNormalMchParams;
import com.jeequan.jeepay.core.model.params.zftpay.ZftpayIsvParams;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
import com.jeequan.jeepay.service.impl.*;
import com.jeequan.jeepay.thirdparty.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/*
* 商户/服务商 配置信息上下文服务
*
* @author terrfly
*
* @date 2021/6/8 17:41
*/
@Slf4j
@Service
public class ConfigContextService implements IConfigContextService {

    /** <商户ID, 商户配置项>  **/
    private static final Map<String, MchInfoConfigContext> mchInfoConfigContextMap = new ConcurrentHashMap<>();

    /** <应用ID, 商户配置上下文>  **/
    private static final Map<String, MchAppConfigBy3rdContext> mchAppConfigContextMap = new ConcurrentHashMap<>();

    /** <服务商号, 服务商配置上下文>  **/
    private static final Map<String, IsvConfigBy3rdContext> isvConfigContextMap = new ConcurrentHashMap<>();

    @Autowired private MchInfoService mchInfoService;
    @Autowired private MchAppService mchAppService;
    @Autowired private IsvInfoService isvInfoService;
    @Autowired private PayInterfaceConfigService payInterfaceConfigService;
    @Autowired
    private MchPayInterfaceConfigService mchPayInterfaceConfigService;
    @Autowired private MchInfoConverter mchInfoConverter;


    /** 获取 [商户配置信息] **/
    public MchInfoConfigContext getMchInfoConfigContext(String mchNo){

        MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchNo);

        //无此数据， 需要初始化
        if(mchInfoConfigContext == null){
            initMchInfoConfigContext(mchNo);
        }

        return mchInfoConfigContextMap.get(mchNo);
    }

    /** 获取 [商户应用支付参数配置信息] **/
    public MchAppConfigBy3rdContext getMchAppConfigContext(String mchNo, String appId){

        MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);

        //无此数据， 需要初始化
        if(mchAppConfigContext == null){
            initMchAppConfigContext(mchNo, appId);
        }

        return mchAppConfigContextMap.get(appId);
    }

    /** 获取 [ISV支付参数配置信息] **/
    public IsvConfigBy3rdContext getIsvConfigContext(String isvNo){

        IsvConfigBy3rdContext isvConfigContext = isvConfigContextMap.get(isvNo);

        //无此数据， 需要初始化
        if(isvConfigContext == null){
            initIsvConfigContext(isvNo);
        }

        return isvConfigContextMap.get(isvNo);
    }


    /** 初始化 [商户配置信息] **/
    @Override
    public synchronized void initMchInfoConfigContext(String mchNo){

        if(!isCache()){ // 当前系统不进行缓存
            return ;
        }

        //商户主体信息
        MchInfo mchInfo = mchInfoService.getById(mchNo);
        if(mchInfo == null){ // 查询不到商户主体， 可能已经删除

            MchInfoConfigContext mchInfoConfigContext = mchInfoConfigContextMap.get(mchNo);

            // 删除所有的商户应用
            if(mchInfoConfigContext != null){
                mchInfoConfigContext.getAppMap().forEach((k, v) -> mchAppConfigContextMap.remove(k));
            }

            mchInfoConfigContextMap.remove(mchNo);
            return ;
        }

        MchInfoConfigContext mchInfoConfigContext = new MchInfoConfigContext();

        // 设置商户信息
        mchInfoConfigContext.setMchNo(mchInfo.getMchNo());
        mchInfoConfigContext.setMchType(mchInfo.getType());
        mchInfoConfigContext.setMchInfo(mchInfo);
        mchAppService.lambdaQuery().list().forEach(mchApp -> {
            MchApp model = mchInfoConverter.toModel(mchApp);
            //1. 更新商户内appId集合
            mchInfoConfigContext.putMchApp(model);

            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(mchApp.getAppId());
            if(mchAppConfigContext != null){
                mchAppConfigContext.setMchApp(model);
                mchAppConfigContext.setMchNo(mchInfo.getMchNo());
                mchAppConfigContext.setMchType(mchInfo.getType());
                mchAppConfigContext.setMchInfo(mchInfo);
            }
        });

        mchInfoConfigContextMap.put(mchNo, mchInfoConfigContext);
    }

    /** 初始化 [商户应用支付参数配置信息] **/
    @Override
    public synchronized void initMchAppConfigContext(String mchNo, String appId){

        if(!isCache()){ // 当前系统不进行缓存
            return ;
        }

        // 获取商户的配置信息
        MchInfoConfigContext mchInfoConfigContext = getMchInfoConfigContext(mchNo);
        if(mchInfoConfigContext == null){ // 商户信息不存在
            return;
        }

        // 查询商户应用信息主体
        MchAppEntity dbMchApp = mchAppService.getById(appId);

        //DB已经删除
        if(dbMchApp == null){
            mchAppConfigContextMap.remove(appId);  //清除缓存信息
            mchInfoConfigContext.getAppMap().remove(appId); //清除主体信息中的appId
            return ;
        }


        // 商户应用mchNo 与参数不匹配
        if(!dbMchApp.getMchNo().equals(mchNo)){
            return;
        }

        MchApp model = mchInfoConverter.toModel(dbMchApp);
        //更新商户信息主体中的商户应用
        mchInfoConfigContext.putMchApp(model);

        //商户主体信息
        MchInfo mchInfo = mchInfoConfigContext.getMchInfo();
        MchAppConfigBy3rdContext mchAppConfigContext = new MchAppConfigBy3rdContext();

        // 设置商户信息
        mchAppConfigContext.setAppId(appId);
        mchAppConfigContext.setMchNo(mchInfo.getMchNo());
        mchAppConfigContext.setMchType(mchInfo.getType());
        mchAppConfigContext.setMchInfo(mchInfo);
        mchAppConfigContext.setMchApp(model);

        // 查询商户的所有支持的参数配置
        List<PayInterfaceConfig> allConfigList = payInterfaceConfigService.list(PayInterfaceConfig.gw()
                .select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getIfParams)
                .eq(PayInterfaceConfig::getState, CS.YES)
                .eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.MCH_APP)
                .eq(PayInterfaceConfig::getInfoId, appId)
        );

        //  ！！ 无论 普通商户 或者 特约商户 都有可能包含 oauth2参数 ！！
        // 查询支付宝的 oauth2配置；
        PayInterfaceConfig alipayOauth2Config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP_OAUTH2, appId, CS.IF_CODE.ALIPAY);
        AlipayOauth2Params alipayOauth2Params = Oauth2Params.factory(CS.IF_CODE.ALIPAY, (alipayOauth2Config == null ? null : alipayOauth2Config.getIfParams()), AlipayOauth2Params.class);
        if(alipayOauth2Params != null){
            mchAppConfigContext.getOauth2ParamsMap().put(CS.IF_CODE.ALIPAY, alipayOauth2Params);
        }

        // 查询微信的 oauth2配置；
        PayInterfaceConfig wxpayOauth2Config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.MCH_APP_OAUTH2, appId, CS.IF_CODE.WXPAY);
        WxpayOauth2Params wxpayOauth2Params = Oauth2Params.factory(CS.IF_CODE.WXPAY, (wxpayOauth2Config == null ? null : wxpayOauth2Config.getIfParams()), WxpayOauth2Params.class);
        if(wxpayOauth2Params != null){
            mchAppConfigContext.getOauth2ParamsMap().put(CS.IF_CODE.WXPAY, wxpayOauth2Params);
        }

        // 普通商户
        if(mchInfo.getType() == CS.MCH_TYPE_NORMAL){

            for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
                mchAppConfigContext.getNormalMchParamsMap().put(
                        payInterfaceConfig.getIfCode(),
                        NormalMchParams.factory(payInterfaceConfig.getIfCode(), payInterfaceConfig.getIfParams())
                );
            }

            //放置alipay client
            AlipayNormalMchParams alipayParams = mchAppConfigContext.getNormalMchParamsByIfCode(CS.IF_CODE.ALIPAY, AlipayNormalMchParams.class);
            if(alipayParams != null || alipayOauth2Params != null){
                mchAppConfigContext.setAlipayClientWrapper(AlipayClientWrapper.buildAlipayClientWrapper(alipayParams, alipayOauth2Params));
            }

            //放置 wxJavaService
            WxpayNormalMchParams wxpayParams = mchAppConfigContext.getNormalMchParamsByIfCode(CS.IF_CODE.WXPAY, WxpayNormalMchParams.class);
            if(wxpayParams != null || wxpayOauth2Params != null){
                mchAppConfigContext.setWxServiceWrapper(WxServiceWrapper.buildWxServiceWrapper(wxpayParams, wxpayOauth2Params));
            }


        }else{ //服务商模式商户
            for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
                mchAppConfigContext.getIsvsubMchParamsMap().put(
                        payInterfaceConfig.getIfCode(),
                        IsvsubMchParams.factory(payInterfaceConfig.getIfCode(), payInterfaceConfig.getIfParams())
                );
            }

            //TODO 商户现在会关联多个服务商，不清楚后续操作的情况下，先屏蔽以下代码
//            mchAppConfigContext.setIsvConfigContext(getIsvConfigContext(mchInfo.getIsvNo()));

        }

        mchAppConfigContextMap.put(appId, mchAppConfigContext);
    }


    /** 初始化 [ISV支付参数配置信息]  **/
    @Override
    public synchronized void initIsvConfigContext(String isvNo){

        if(!isCache()){ // 当前系统不进行缓存
            return ;
        }

        //查询出所有商户的配置信息并更新
//        List<String> mchNoList = new ArrayList<>();
//        mchInfoService.list(com.jeequan.jeepay.db.entity.MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getIsvNo, isvNo)).forEach(r -> mchNoList.add(r.getMchNo()));
//
//        // 查询出所有 所属当前服务商的所有应用集合
//        List<String> mchAppIdList = new ArrayList<>();
//        if(!mchNoList.isEmpty()){
//            mchAppService.lambdaQuery().select(MchAppEntity::getAppId).in(MchAppEntity::getMchNo, mchNoList).list()
//                            .forEach(r -> mchAppIdList.add(r.getAppId()));
//        }

        IsvConfigBy3rdContext isvConfigContext = new IsvConfigBy3rdContext();
        IsvInfo isvInfo = isvInfoService.getById(isvNo);
        if(isvInfo == null){

//            for (String appId : mchAppIdList) {
//                //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
//                MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
//                if(mchAppConfigContext != null){
//                    mchAppConfigContext.setIsvConfigContext(null);
//                }
//            }

            isvConfigContextMap.remove(isvNo); // 服务商有商户不可删除， 此处不再更新商户下的配置信息
            return ;
        }

        // 设置商户信息
        isvConfigContext.setIsvNo(isvInfo.getIsvNo());
        isvConfigContext.setIsvInfo(isvInfo);

        // 查询服务商的所有支持的参数配置
        List<PayInterfaceConfig> allConfigList = payInterfaceConfigService.list(PayInterfaceConfig.gw()
                .select(PayInterfaceConfig::getIfCode, PayInterfaceConfig::getIfParams, PayInterfaceConfig::getOauth2InfoId)
                .eq(PayInterfaceConfig::getState, CS.YES)
                .eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.ISV)
                .eq(PayInterfaceConfig::getInfoId, isvNo)
        );

        List<com.jeequan.jeepay.db.entity.MchPayInterfaceConfig> allConfigList2 = mchPayInterfaceConfigService.lambdaQuery()
                .select(com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getIfCode, com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getIfParams, com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getOauth2InfoId)
                .eq(com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getState, CS.YES)
                .eq(com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.ISV)
                .eq(com.jeequan.jeepay.db.entity.MchPayInterfaceConfig::getInfoId, isvNo).list();

        // 同时存储两张表的数据
        for (PayInterfaceConfig payInterfaceConfig : allConfigList) {
            isvConfigContext.getIsvParamsMap().put(
                    payInterfaceConfig.getIfCode(),
                    IsvParams.factory(payInterfaceConfig.getIfCode(), payInterfaceConfig.getIfParams())
            );

            // 选择的oauth2条目
            isvConfigContext.getOauth2SelectedInfoId().put(payInterfaceConfig.getIfCode(), payInterfaceConfig.getOauth2InfoId());
        }


        for (com.jeequan.jeepay.db.entity.MchPayInterfaceConfig payInterfaceConfig : allConfigList2) {
            isvConfigContext.getIsvParamsMap().put(
                    payInterfaceConfig.getId(),
                    IsvParams.factory(payInterfaceConfig.getIfCode(), payInterfaceConfig.getIfParams())
            );
        }

        // 设置默认的oauth2参数
        this.commonsPutIsvOauth2Map(isvConfigContext, isvNo, true);

        // 查询出所有的 其他 自定义  oauth2参数。  并去重。
        String infoIdLike = isvNo + "_LIST_";
        List<PayInterfaceConfig> diyList =
                payInterfaceConfigService.list(PayInterfaceConfig.gw().select(PayInterfaceConfig::getInfoId)
                        .like(PayInterfaceConfig::getInfoId, infoIdLike).eq(PayInterfaceConfig::getInfoType, CS.SYS_ROLE_TYPE.ISV_OAUTH2));

        // 去重
        Set<String> infoIdSet = new HashSet<>();
        for (PayInterfaceConfig item : diyList) {
            infoIdSet.add(item.getInfoId());
        }

        // 设置 diy 的oauth2参数
        for (String infoId : infoIdSet) {
            this.commonsPutIsvOauth2Map(isvConfigContext, infoId, false);
        }


        isvConfigContextMap.put(isvNo, isvConfigContext);

        //查询出所有商户的配置信息并更新
//        for (String appId : mchAppIdList) {
//            //将更新已存在缓存的商户配置信息 （每个商户下存储的为同一个 服务商配置的对象指针）
//            MchAppConfigContext mchAppConfigContext = mchAppConfigContextMap.get(appId);
//            if(mchAppConfigContext != null){
//                mchAppConfigContext.setIsvConfigContext(isvConfigContext);
//            }
//        }
    }


    private boolean isCache(){
        return SysConfigService.IS_USE_CACHE;
    }

    // 通用放置 oauth2参数的函数。
    private void commonsPutIsvOauth2Map(IsvConfigBy3rdContext isvConfigContext, String infoId, boolean isDefault){

        // 查询支付宝的 oauth2配置；
        PayInterfaceConfig alipayOauth2Config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.ISV_OAUTH2, infoId, CS.IF_CODE.ALIPAY);
        AlipayOauth2Params alipayOauth2Params = Oauth2Params.factory(CS.IF_CODE.ALIPAY, (alipayOauth2Config == null ? null : alipayOauth2Config.getIfParams()), AlipayOauth2Params.class);
        if(alipayOauth2Params != null){

            if(isDefault){
                isvConfigContext.getOauth2ParamsMap().put(CS.IF_CODE.ALIPAY, alipayOauth2Params);
            }else{
                isvConfigContext.putOauth2ParamsMapByDiyList(infoId, CS.IF_CODE.ALIPAY, alipayOauth2Params);
            }

        }

        // 查询微信的 oauth2配置；
        PayInterfaceConfig wxpayOauth2Config = payInterfaceConfigService.getByInfoIdAndIfCode(CS.SYS_ROLE_TYPE.ISV_OAUTH2, infoId, CS.IF_CODE.WXPAY);
        WxpayOauth2Params wxpayOauth2Params = Oauth2Params.factory(CS.IF_CODE.WXPAY, (wxpayOauth2Config == null ? null : wxpayOauth2Config.getIfParams()), WxpayOauth2Params.class);
        if(wxpayOauth2Params != null){

            if(isDefault){
                isvConfigContext.getOauth2ParamsMap().put(CS.IF_CODE.WXPAY, wxpayOauth2Params);
            }else{
                isvConfigContext.putOauth2ParamsMapByDiyList(infoId, CS.IF_CODE.WXPAY, wxpayOauth2Params);
            }

        }

        //放置alipay client
        AlipayIsvParams alipayParams = isDefault ? isvConfigContext.getIsvParams(CS.IF_CODE.ALIPAY, AlipayIsvParams.class) : null;
        if(alipayParams != null || alipayOauth2Params != null){

            if(isDefault){
                isvConfigContext.setAlipayClientWrapper(AlipayClientWrapper.buildAlipayClientWrapper(alipayParams, alipayOauth2Params));
            }else{
                isvConfigContext.getAlipayClientWrapperByOauth2diyMap().put(infoId, AlipayClientWrapper.buildAlipayClientWrapper(alipayParams, alipayOauth2Params));
            }

        }

        //放置zftpay client
        ZftpayIsvParams zftpayParams = isDefault ? isvConfigContext.getIsvParams(CS.IF_CODE.ZFTPAY, ZftpayIsvParams.class) : null;
        if(zftpayParams != null){
            isvConfigContext.setZftpayClientWrapper(ZftpayClientWrapper.buildZftpayClientWrapper(zftpayParams));
        }

        //放置 wxJavaService
        WxpayIsvParams wxpayParams = isDefault ? isvConfigContext.getIsvParams(CS.IF_CODE.WXPAY, WxpayIsvParams.class) : null;
        if(wxpayParams != null || wxpayOauth2Params != null){

            if(isDefault){
                isvConfigContext.setWxServiceWrapper(WxServiceWrapper.buildWxServiceWrapper(wxpayParams, wxpayOauth2Params));
            }else{
                isvConfigContext.getWxServiceWrapperByOauth2diyMap().put(infoId, WxServiceWrapper.buildWxServiceWrapper(wxpayParams, wxpayOauth2Params));
            }
        }
    }

}
