package com.huigou.bpm.webservice.ws.application.impl;

import com.huigou.bpm.webservice.application.WebServiceConfigTypeApplication;
import com.huigou.bpm.webservice.domain.model.OtherSystemConfig;
import com.huigou.bpm.webservice.domain.model.WebServiceConfigType;
import com.huigou.bpm.webservice.model.RuleResult;
import com.huigou.bpm.webservice.model.WsRequest;
import com.huigou.bpm.webservice.model.WsResponse;
import com.huigou.bpm.webservice.repository.OtherSystemConfigRepository;
import com.huigou.bpm.webservice.ws.application.WebServiceApplication;
import com.huigou.context.Operator;
import com.huigou.exception.ApplicationException;
import com.huigou.rule.application.RuleApplication;
import com.huigou.rule.domain.model.Rule;
import com.huigou.uasp.bmp.operator.OperatorApplication;
import com.huigou.util.ClassHelper;
import com.huigou.util.JSONUtil;
import com.huigou.util.StringUtil;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import javax.jws.WebService;
import java.lang.reflect.Method;
import java.util.*;

@WebService(endpointInterface = "com.huigou.bpm.webservice.ws.application.impl.WebServiceApplicationImpl",serviceName = "webServiceApplication", targetNamespace = "http://bpm.service.com/")
public class WebServiceApplicationImpl implements WebServiceApplication {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private WebServiceConfigTypeApplication webServiceConfigTypeApplication;
    @Autowired
    private OtherSystemConfigRepository otherSystemConfigRepository;
    @Autowired
    private OperatorApplication operatorApplication;
    @Autowired
    private RuleApplication ruleApplication;

    @Override
    public WsResponse generalInterface(WsRequest request) {

        WsResponse wsResponse = new WsResponse();
        try{
            if(StringUtil.isBlank(request.getAppId())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("系统ID【appId】:不能为空！");
                throw new ApplicationException("系统ID【appId】:不能为空！");
            }
            if(StringUtil.isBlank(request.getAppCode())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("系统编号【appCode】:不能为空！");
                throw new ApplicationException("系统编号【appCode】:不能为空！");
            }
            if(StringUtil.isBlank(request.getRequestCategory())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("请求类别【requestCategory】:不能为空！");
                throw new ApplicationException("请求类别【requestCategory】:不能为空！");
            }
            OtherSystemConfig config = otherSystemConfigRepository.findBySystemIdAndCodeAndSystemServiceCategory(request.getAppId(),request.getAppCode(),request.getRequestCategory());
            if(config==null){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("无权限访问接口，请联系管理员！");
                throw new ApplicationException("无权限访问接口，请联系管理员！");
            }
            if(config.getStatus()==0){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("访问接口权限已失效，请联系管理员！");
                throw new ApplicationException("访问接口权限已失效，请联系管理员！");
            }
            WebServiceConfigType configType = webServiceConfigTypeApplication.findByCode(config.getSystemServiceCategory());
            if(configType==null){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("未找到对应的接口类型配置，请联系管理员！");
                throw new ApplicationException("未找到对应的接口类型配置，请联系管理员！");
            }

            Object application = applicationContext.getBean(configType.getSystemServiceCode());
            Object result = null;
            Method method = null;
            boolean hasMethod = false;

            String[] types = configType.getServiceParamTypes().split(",");
            String[] paramNames = configType.getServiceParamters().split(",");
            Method[] methods = application.getClass().getMethods();
            for(Method md : methods){
                if(checkMethod(md,configType)){
                    hasMethod= true;
                    List<Object> param = new ArrayList<>(types.length);
                    for (int i = 0; i < types.length; i++) {
                        if("com.huigou".equals(types[i])){
                            Map<String,Object> map = (Map<String,Object>)ClassHelper.clone(request.getParam());
                            if(types[i].endsWith("QueryRequest")){
                                Operator operator = operatorApplication.createOperatorByLoginName(request.getAppCode());
                                map.put("operator",operator);
                            }
                            Object data = ClassHelper.fromMap(getTypeClass(types[i]),map);
                            param.add(data);
                        }else{
                            param.add(request.getParam().get(paramNames[i]));
                        }
                    }
                    if(configType.getIsEnableRule()>0||config.getIsEnableRule()>0){
                        RuleResult ruleResult = new RuleResult();//规则验证返回数据
                        Rule configTypeRule = null;
                        Rule configRule = null;
                        StringBuffer ruleName = new StringBuffer();
                        StringBuffer ruleStr = new StringBuffer();
                        if(configType.getIsEnableRule()>0){
                            configTypeRule = ruleApplication.findByCode(configType.getRuleCode());
                            if(configTypeRule==null){
                                throw new ApplicationException("未找到接口类型【"+configType.getName()+"】配置的规则信息，请联系管理员！");
                            }
                            ruleStr = ruleStr.append(new String(Base64.getDecoder().decode(configTypeRule.getRules())));
                            ruleName = ruleName.append(configType.getRuleName());
                        }
                        if(config.getIsEnableRule()>0){
                            configRule = ruleApplication.findByCode(configType.getRuleCode());
                            if(configRule==null){
                                throw new ApplicationException("未找到接口【"+config.getName()+"】配置的规则信息，请联系管理员！");
                            }
                            if(ruleStr.length()>0){
                                ruleStr.append("\n");
                                ruleName = ruleName.append("-");
                            }
                            ruleStr = ruleStr.append(new String(Base64.getDecoder().decode(configRule.getRules())));
                            ruleName = ruleName.append(config.getRuleName());
                        }
                        KieHelper kh = new KieHelper();
                        kh.addContent(ruleStr.toString(), ResourceType.DRL);
                        KieSession kieSession = kh.build().newKieSession();
                        kieSession.insert(ruleResult);//返回参数
//                        kieSession.insert(application);//需要执行的实现类
                        kieSession.insert(param);//方法参数
                        kieSession.fireAllRules();
                        kieSession.dispose();
                        if(ruleResult.isSuccess()){
                           result = md.invoke(application,param.toArray());
                        }else{
                            throw new ApplicationException("未通过【"+ruleName.toString()+"】规则验证，请联系管理员！");
                        }
                    }else{
                        result = md.invoke(application,param.toArray());
                    }
                    break;
                }
            }
            if(!hasMethod){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("未找到对应的执行方法，请联系管理员！");
                throw new ApplicationException("未找到对应的执行方法，请联系管理员！");
            }
            wsResponse.setStatus("SUCCESS");
            if(result !=null){
                Map<String,String> map = new HashMap<String,String>();
                Map<String,Object> omap = ClassHelper.beanToMap(result);
                for(Map.Entry<String,Object> m: omap.entrySet()){
                    if(m.getValue()!=null){
                        map.put(m.getKey(),m.getValue().toString());
                    }
                }
                wsResponse.setData(map);
            }

            return wsResponse;
        } catch (Exception e){
            if(e.getClass().equals(ApplicationException.class)){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg(e.getMessage());
                return wsResponse;
            }else{
                e.printStackTrace();
                throw new ApplicationException("系统错误，请联系管理员！");
            }
        }
    }

    @Override
    public String generalInterfaceToJson(WsRequest request) {
        WsResponse wsResponse = new WsResponse();
        try{
            if(StringUtil.isBlank(request.getAppId())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("系统ID【appId】:不能为空！");
                throw new ApplicationException("系统ID【appId】:不能为空！");
            }
            if(StringUtil.isBlank(request.getAppCode())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("系统编号【appCode】:不能为空！");
                throw new ApplicationException("系统编号【appCode】:不能为空！");
            }
            if(StringUtil.isBlank(request.getRequestCategory())){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("请求类别【requestCategory】:不能为空！");
                throw new ApplicationException("请求类别【requestCategory】:不能为空！");
            }
            OtherSystemConfig config = otherSystemConfigRepository.findBySystemIdAndCodeAndSystemServiceCategory(request.getAppId(),request.getAppCode(),request.getRequestCategory());
            if(config==null){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("无权限访问接口，请联系管理员！");
                throw new ApplicationException("无权限访问接口，请联系管理员！");
            }
            if(config.getStatus()==0){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("访问接口权限已失效，请联系管理员！");
                throw new ApplicationException("访问接口权限已失效，请联系管理员！");
            }
            WebServiceConfigType configType = webServiceConfigTypeApplication.findByCode(config.getSystemServiceCategory());
            if(configType==null){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("未找到对应的接口类型配置，请联系管理员！");
                throw new ApplicationException("未找到对应的接口类型配置，请联系管理员！");
            }

            Object application = applicationContext.getBean(configType.getSystemServiceCode());
            Object result = null;
            Method method = null;
            boolean hasMethod = false;

            String[] types = configType.getServiceParamTypes().split(",");
            String[] paramNames = configType.getServiceParamters().split(",");
            Method[] methods = application.getClass().getMethods();
            for(Method md : methods){
                if(checkMethod(md,configType)){
                    hasMethod= true;
                    List<Object> param = new ArrayList<>(types.length);
                    for (int i = 0; i < types.length; i++) {
                        if("com.huigou".equals(types[i])){
                            Map<String,Object> map = (Map<String,Object>)ClassHelper.clone(request.getParam());
                            if(types[i].endsWith("QueryRequest")){
                                Operator operator = operatorApplication.createOperatorByLoginName(request.getAppCode());
                                map.put("operator",operator);
                            }
                            Object data = ClassHelper.fromMap(getTypeClass(types[i]),map);
                            param.add(data);
                        }else{
                            if("List".equals(types[i])){
                                String list = request.getParam().get(paramNames[i]);
                                if(StringUtil.isNotBlank(list)){
                                    param.add(null);
                                }else{
                                    List<String> lists = new ArrayList<String>();
                                    for(String str : list.split(",")){
                                        lists.add(str);
                                    }
                                    param.add(lists);
                                }
                            }else{
                                param.add(request.getParam().get(paramNames[i]));
                            }
                        }
                    }
                    if(configType.getIsEnableRule()>0||config.getIsEnableRule()>0){
                        RuleResult ruleResult = new RuleResult();//规则验证返回数据
                        Rule configTypeRule = null;
                        Rule configRule = null;
                        StringBuffer ruleName = new StringBuffer();
                        StringBuffer ruleStr = new StringBuffer();
                        if(configType.getIsEnableRule()>0){
                            configTypeRule = ruleApplication.findByCode(configType.getRuleCode());
                            if(configTypeRule==null){
                                throw new ApplicationException("未找到接口类型【"+configType.getName()+"】配置的规则信息，请联系管理员！");
                            }
                            ruleStr = ruleStr.append(new String(Base64.getDecoder().decode(configTypeRule.getRules())));
                            ruleName = ruleName.append(configType.getRuleName());
                        }
                        if(config.getIsEnableRule()>0){
                            configRule = ruleApplication.findByCode(configType.getRuleCode());
                            if(configRule==null){
                                throw new ApplicationException("未找到接口【"+config.getName()+"】配置的规则信息，请联系管理员！");
                            }
                            if(ruleStr.length()>0){
                                ruleStr.append("\n");
                                ruleName = ruleName.append("-");
                            }
                            ruleStr = ruleStr.append(new String(Base64.getDecoder().decode(configRule.getRules())));
                            ruleName = ruleName.append(config.getRuleName());
                        }
                        KieHelper kh = new KieHelper();
                        kh.addContent(ruleStr.toString(), ResourceType.DRL);
                        KieSession kieSession = kh.build().newKieSession();
                        kieSession.insert(ruleResult);//返回参数
//                        kieSession.insert(application);//需要执行的实现类
                        kieSession.insert(param);//方法参数
                        kieSession.fireAllRules();
                        kieSession.dispose();
                        if(ruleResult.isSuccess()){
                            result = md.invoke(application,param.toArray());
                        }else{
                            throw new ApplicationException("未通过【"+ruleName.toString()+"】规则验证，请联系管理员！");
                        }
                    }else{
                        result = md.invoke(application,param.toArray());
                    }
                    break;
                }
            }
            if(!hasMethod){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg("未找到对应的执行方法，请联系管理员！");
                throw new ApplicationException("未找到对应的执行方法，请联系管理员！");
            }
            wsResponse.setStatus("SUCCESS");
            if(result !=null){
                Map<String,String> map = new HashMap<String,String>();
                Map<String,Object> omap = ClassHelper.beanToMap(result);
                for(Map.Entry<String,Object> m: omap.entrySet()){
                    if(m.getValue()!=null){
                        map.put(m.getKey(),m.getValue().toString());
                    }
                }
                wsResponse.setData(map);
            }

            return JSONUtil.toString(wsResponse);
        } catch (Exception e){
            if(e.getClass().equals(ApplicationException.class)){
                wsResponse.setStatus("ERROR");
                wsResponse.setMsg(e.getMessage());
                return JSONUtil.toString(wsResponse);
            }else{
                e.printStackTrace();
                throw new ApplicationException("系统错误，请联系管理员！");
            }
        }
    }

    /**
     * 更具类型获取当前类型的Class
     * @param type
     * @return
     */
    private Class getTypeClass(String type){
        switch (type){
            case "String":
                return String.class;
            case "int":
                return int.class;
            case "Integer":
                return Integer.class;
            case "Float":
                return Float.class;
            case "float":
                return float.class;
            default:
                if(StringUtil.isNotBlank(type)&&type.indexOf("com.huigou")!=-1){
                    try{
                        return Class.forName(type);
                    }catch (Exception e){
                        e.printStackTrace();
                    }

                }
                throw new RuntimeException(String.format("无效的参数类型“%s”。", new Object[] { type }));
        }
    }

    /**
     * 验证是否是正确的执行方法
     * @param method
     * @param configType
     * @return
     */
    private boolean checkMethod(Method method,WebServiceConfigType configType){
        String[] types = configType.getServiceParamTypes().split(",");
        if(configType.getServiceMethod().equals(method.getName())
                &&types.length==method.getParameterCount()){
            Class[] classes = method.getParameterTypes();
            for (int i = 0; i < classes.length; i++) {
                if(!getTypeClass(types[i]).equals(classes[i])){
                    return false;
                }

            }
            return true;
        }
        return false;
    }
}
