package cn.cslg.pas.common.utils.auth;

import cn.cslg.pas.common.model.DataSource;
import cn.cslg.pas.common.model.PersonnelVO;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

@Component
public class TreeUtils {
    /**
     * 将二叉树json对象转为sql where后的条件语句
     * liRJ
     *
     * @param jsonObject  要处理的jsonObject对象
     * @param dataSource  要使用的数据字典
     * @param personnelVO 登录人的信息
     * @return 拼接的sql
     */
    // 处理sql语句，返回拼接sql
    public static String reSql(JSONObject jsonObject, List<DataSource> dataSource, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        String sql;
        //判断是否为规则，是的话则返回为“”，不对其他sql条件产生影响
        if (jsonObject.get("nodeType").equals("logic")) {
            sql = "";
        }
        //符合二叉树形式
        else if (jsonObject.containsKey("left") && jsonObject.containsKey("right")) {
            //将二叉树转换为sql条件
            sql = recursionTree(jsonObject, dataSource, personnelVO);
        }
        // 不符合二叉树形式（单条数据）
        else {
            //获得规则的field字段，作为sql条件的栏位
            String field = jsonObject.get("field").toString();
            //获得规则的栏位值，并且要对值进行识别操作
            String value = distinguishFields(jsonObject.get("value").toString(), dataSource, personnelVO);
            if (jsonObject.get("opr").toString().equals("FIND_IN_SET")) {
                sql = "FIND_IN_SET(" + value + "," + field + ")";
            } else {
                sql = field + " " + jsonObject.get("opr").toString() + " " + value;
            }
        }

        return sql;
    }

    /**
     * 将二叉树json对象转为sql where后的条件语句
     * liRJ
     *
     * @param jsonObject  要处理的jsonObject对象
     * @param dataSource  要使用的数据字典
     * @param personnelVO 登录人的信息
     * @return 拼接的sql
     */
    // 处理规则
    public static String reCompute(JSONObject jsonObject, Object[] object, List<DataSource> dataSource, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        String sql;
        //判断是否为sql类型规则，是的话规则转换为1==1，不对其他规则产生影响
        if (jsonObject.get("nodeType").equals("sql")) {
            sql = "1==1";
        }
        //符合二叉树形式
        else if (jsonObject.containsKey("left") && jsonObject.containsKey("right")) {
            //将二叉树转换为规则判断
            sql = cRecursionTree(jsonObject, object, dataSource, personnelVO);
        }
        // 不符合二叉树形式(单条数据)
        else {
            //获得规则的 field字段，并进行识别操作
            String field = distinguishFields(jsonObject.get("field").toString(), object, dataSource, personnelVO);
            //获得规则的 value字段，并进行识别操作
            String value = distinguishValues(jsonObject.get("value").toString(), object);
            //获得规则的 运算符字段，并进行识别操作
            String opr = distinguishLogic(jsonObject.getString("nodeType"), jsonObject.getString("opr"));
            //field 和value若为以,隔开的数组时，将被拆开，并合成为新的规则
            sql = arrayEqlToString(field, value, opr);
        }

        return sql;
    }

    /**
     * 递归将二叉树转换为字符串
     * liRJ
     *
     * @param jsonObject jsonObject
     */
    //将二叉树转换为sql条件
    public static String recursionTree(JSONObject jsonObject, List<DataSource> dataSource, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        String str1;
        String str2;
        // 获得规则左边
        JSONObject jsonLeft = jsonObject.getJSONObject("left");
        // 获得规则右边
        JSONObject jsonRight = jsonObject.getJSONObject("right");
        //判断是否含有left分支，有的话进行递归
        if (jsonLeft.containsKey("left")) {
            str1 = recursionTree(jsonLeft, dataSource, personnelVO);//递归
        }
        //没有的话解析字符串拼接成子sql
        else {
            String field = jsonLeft.get("field").toString();
            //获得规则的 value字段，并进行识别操作
            String value = distinguishFields(jsonLeft.get("value").toString(), dataSource, personnelVO); //没有的话解析字符串拼接成子sql
            if (jsonLeft.get("opr").toString().equals("FIND_IN_SET")) {
                str1 = "FIND_IN_SET(" + value + "," + field + ")";
            } else {
                str1 = field + " " + jsonLeft.get("opr").toString() + " " + value;
            }
        }
        //同上部分处理left分支
        if (jsonRight.containsKey("right")) {
            str2 = recursionTree(jsonRight, dataSource, personnelVO);
        } else {
            String field = jsonRight.get("field").toString();
            String value = distinguishFields(jsonRight.get("value").toString(), dataSource, personnelVO);
            if (jsonRight.get("opr").toString().equals("FIND_IN_SET")) {
                str2 = "FIND_IN_SET(" + value + "," + field + ")";
            } else {
                str2 = field + " " + jsonRight.get("opr").toString() + " " + value;
            }
        }
        return "(" + str1 + ") " + jsonObject.get("logicOpr") + " (" + str2 + ")";
    }

    //将二叉树转换为规则判断
    public static String cRecursionTree(JSONObject jsonObject, Object[] object, List<DataSource> dataSource, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        String str1;
        String str2;
        // 获得规则左边
        JSONObject jsonLeft = jsonObject.getJSONObject("left");
        // 获得规则右边
        JSONObject jsonRight = jsonObject.getJSONObject("right");
        //判断是否含有left分支，有的话进行递归
        if (jsonLeft.containsKey("left")) {
            str1 = cRecursionTree(jsonLeft, object, dataSource, personnelVO);
        } else {
            //获得规则的 field字段，并进行识别操作
            String field = distinguishFields(jsonLeft.get("field").toString(), object, dataSource, personnelVO);
            //获得规则的 value字段，并进行识别操作
            String value = distinguishValues(jsonLeft.get("value").toString(), object);
            //获得规则的 opr字段，并进行识别操作
            String opr = distinguishLogic(jsonLeft.getString("nodeType"), jsonLeft.getString("opr"));
            str1 = arrayEqlToString(field, value, opr);
        }
        //同上部分处理right分支
        if (jsonRight.containsKey("right")) {
            str2 = cRecursionTree(jsonRight, object, dataSource, personnelVO);
        } else {
            String field = distinguishFields(jsonRight.get("field").toString(), object, dataSource, personnelVO);
            String value = distinguishValues(jsonRight.get("value").toString(), object);
            String opr = distinguishLogic(jsonRight.getString("nodeType"), jsonRight.getString("opr"));
            str2 = arrayEqlToString(field, value, opr);
        }

        return "(" + str1 + ") " + distinguishLogic(jsonObject.getString("nodeType"), jsonObject.getString("logicOpr")) + " (" + str2 + ")";
    }

    //对field和value部分进行计算 sql查询
    public static String distinguishFields(String field, List<DataSource> dataSources, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        //获得登录用户部门列表信息
        List<PersonnelVO.DP> dps = personnelVO.getDpList();
        //获得登录用户角色列表信息
        List<PersonnelVO.PerRole> perRoles = personnelVO.getRList();
        String tem = "";
        String reField = field;
        //如果参数是sql语句
        if (field.contains("select")) {
            for (DataSource dataSource : dataSources) {
                String sourceField = dataSource.getDataSourceField();
                if (field.contains("local." + sourceField)) {
                    // 判断是否是部门信息
                    if (sourceField.contains("DP.")) {
                        // 分割字符串获得部门字段
                        String Fields = sourceField.split("\\.")[1];
                        // 遍历部门信息，用反射将对应字段转换成（*,*,...)格式
                        for (PersonnelVO.DP dp : dps) {
                            Class<?> DPClass = dp.getClass();
                            Field dataField = DPClass.getDeclaredField(Fields);
                            dataField.setAccessible(true);
                            tem = dataField.get(dp).toString() + ",";

                        }
                        reField = sourceField.replace("local." + sourceField, "(" + tem.substring(0, tem.length() - 1) + ")");
                    }
                    //判断是否是角色信息(处理过程同部门信息处理过程)
                    else if (sourceField.contains("PerRole.")) {
                        String Fields = sourceField.split("\\.")[1];
                        for (PersonnelVO.PerRole perRole : perRoles) {
                            Class<?> DPClass = perRole.getClass();
                            Field dataField = DPClass.getDeclaredField(Fields);
                            dataField.setAccessible(true);
                            tem = dataField.get(perRole).toString() + ",";
                        }
                        reField = sourceField.replace("local." + sourceField, "(" + tem.substring(0, tem.length() - 1) + ")");
                    } else {
                        Class<?> personClass = personnelVO.getClass();
                        Field dataField = personClass.getDeclaredField(sourceField);
                        dataField.setAccessible(true);
                        reField = reField.replace("local." + sourceField, dataField.get(personnelVO).toString());
                    }
                }
            }
        }
        //遍历字典数据
        else {
            for (DataSource dataSource : dataSources) {
                // 如果匹配上字典字段则进行处理
                if (field.equals(dataSource.getDataSourceField())) {
                    // 判断是否是部门信息
                    if (field.contains("DP.")) {
                        // 分割字符串获得部门字段
                        String Fields = field.split("\\.")[1];
                        // 遍历部门信息，用反射将对应字段转换成（*,*,...)格式
                        for (PersonnelVO.DP dp : dps) {
                            Class<?> DPClass = dp.getClass();
                            Field dataField = DPClass.getDeclaredField(Fields);
                            dataField.setAccessible(true);
                            tem = dataField.get(dp).toString() + ",";

                        }
                        reField = "(" + tem.substring(0, tem.length() - 1) + ")";
                    }
                    //判断是否是角色信息(处理过程同部门信息处理过程)
                    else if (field.contains("PerRole.")) {
                        String Fields = field.split("\\.")[1];
                        for (PersonnelVO.PerRole perRole : perRoles) {
                            Class<?> DPClass = perRole.getClass();
                            Field dataField = DPClass.getDeclaredField(Fields);
                            dataField.setAccessible(true);
                            tem = dataField.get(perRole).toString() + ",";
                        }
                        reField = "(" + tem.substring(0, tem.length() - 1) + ")";
                    } else {
                        Class<?> personClass = personnelVO.getClass();
                        Field dataField = personClass.getDeclaredField(field);
                        dataField.setAccessible(true);
                        reField = dataField.get(personnelVO).toString();
                        break;
                    }
                }
            }
        }
        return reField;
    }

    //对field部分进行计算
    public static String distinguishFields(String field, Object[] object, List<DataSource> dataSources, PersonnelVO personnelVO) throws NoSuchFieldException, IllegalAccessException {
        String reField = "'" + field + "'";
        //反射获方法的参数值
        Class<?> jsonClass = object[0].getClass();
        for (Field field1 : jsonClass.getDeclaredFields()) {
            if (field1.getName().equals(field)) {     //判断field的值是否和参数名一样，一样的话变为参数值
                Field dataField = jsonClass.getDeclaredField(field);
                dataField.setAccessible(true);//设置data属性为可访问的
                String fie = dataField.get(object[0]).toString();
                reField = "'" + fie + "'";
                break;
            }
        }
        //获得登录用户部门列表信息
        List<PersonnelVO.DP> dps = personnelVO.getDpList();
        //获得登录用户角色列表信息
        List<PersonnelVO.PerRole> perRoles = personnelVO.getRList();
        String tem = "";
        //遍历字典数据
        for (DataSource dataSource : dataSources) {
            // 如果匹配上字典字段则进行处理
            if (field.equals(dataSource.getDataSourceField())) {
                // 判断是否是部门信息
                if (field.contains("DP.")) {
                    // 分割字符串获得部门字段
                    String Fields = field.split("\\.")[1];
                    // 遍历部门信息，用反射将对应字段转换成（*,*,...)格式
                    for (PersonnelVO.DP dp : dps) {
                        Class<?> DPClass = dp.getClass();
                        Field dataField = DPClass.getDeclaredField(Fields);
                        dataField.setAccessible(true);
                        tem = dataField.get(dp).toString() + ",";

                    }
                    reField = tem.substring(0, tem.length() - 1);
                }
                //判断是否是角色信息(处理过程同部门信息处理过程)
                else if (field.contains("PerRole.")) {
                    String Fields = field.split("\\.")[1];
                    for (PersonnelVO.PerRole perRole : perRoles) {
                        Class<?> DPClass = perRole.getClass();
                        Field dataField = DPClass.getDeclaredField(Fields);
                        dataField.setAccessible(true);
                        tem = dataField.get(perRole).toString() + ",";
                    }
                    reField = tem.substring(0, tem.length() - 1);
                } else {
                    Class<?> personClass = personnelVO.getClass();
                    Field dataField = personClass.getDeclaredField(field);
                    dataField.setAccessible(true);
                    reField = "'" + dataField.get(personnelVO).toString() + "'";
                    break;
                }
            }
        }

        return reField;
    }

    //对value部分进行计算
    public static String distinguishValues(String value, Object[] object) throws NoSuchFieldException, IllegalAccessException {
        String reValue = "'" + value + "'";
        //反射获得参数值
        Class<?> jsonClass = object[0].getClass();
        for (Field field1 : jsonClass.getDeclaredFields()) {
            if (field1.getName().equals(value)) {     //判断value的值是否和参数名一样，一样的话变为参数值
                Field dataField = jsonClass.getDeclaredField(value);
                dataField.setAccessible(true);//设置data属性为可访问的
                String fie = dataField.get(object[0]).toString();
                reValue = "'" + fie + "'";
                break;
            }
        }

        return reValue;
    }

    //对应改变运算逻辑
    public static String distinguishLogic(String nodeType, String opr) {
        if (nodeType.equals("logic")) {
            switch (opr) {
                case "=":
                    opr = "==";
                    break;
                case "and":
                    opr = "&&";
                    break;
                case "or":
                    opr = "||";
                    break;
            }
        }

        return opr;
    }

    // 将x,y=z,w 形式改为 x=z||x=w||y=z||y=w形式
    public static String arrayEqlToString(String field, String value, String opr) {
        StringBuilder reStr = new StringBuilder();
        String[] fields = field.split(",");
        String[] values = value.split(",");
        for (int i = 0; i < fields.length; i++) {
            for (int t = 0; t < values.length; t++) {
                reStr.append(i == fields.length - 1 && t == values.length - 1 ? fields[i] + opr + values[t] : fields[i] + opr + values[t] + "||");
            }
        }

        return reStr.toString();
    }
}
