
package com.lideeyunji.tool.framework.sql.build.build.dql;

import com.lideeyunji.tool.framework.sql.build.buildmodel.ExpressionModel;
import com.lideeyunji.tool.framework.sql.build.buildmodel.SQLInterpretContext;
import com.lideeyunji.tool.framework.sql.build.buildmodel.dql.SqlInfoConditionModel;
import com.lideeyunji.tool.framework.sql.build.buildmodel.dql.SqlInfoHavingModel;
import com.lideeyunji.tool.framework.sql.core.dql.select.lideeYunJiQueryWrapper;
import com.lideeyunji.tool.framework.sql.core.model.SqlFormatModel;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @author JX
 * @create 2024-07-29 16:00
 * @dedescription:
 */

public class BuildCondition {

    public lideeYunJiQueryWrapper<Object> wrapper = new lideeYunJiQueryWrapper();

    public SQLInterpretContext context;


    public  SqlFormatModel context2Condition(SqlInfoConditionModel conditionModel){
        List<ExpressionModel> expressions =conditionModel.getExpressions();
        expressions.forEach(expressionModel -> {
            SqlInfoConditionModel.WhereType whereType = expressionModel.getWhereType();
            String column = expressionModel.getColumn();
            Object[] value = expressionModel.getValue();
            switch (whereType) {
                case GT://>
                    gt(column, value);
                    break;
                case GE://>=
                    ge(column, value);
                    break;
                case NE:// !=
                    ne(column, value);
                    break;
                case EQ:// =
                    eq(column, value);
                    break;
                case LT://<
                    lt(column, value);
                    break;
                case LE://<=
                    le(column, value);
                    break;
                case BETWEEN:
                    between(column, value);
                    break;
                case NOT_BETWEEN:
                    notbetween(column, value);
                    break;
                case IN:
                    in(column, value);
                    break;
                case NOT_IN:
                    notIn(column, value);
                    break;
                case LIKE:
                    like(column, value);
                    break;
                case NOT_LIKE:
                    notLike(column, value);
                    break;
                case LIKE_LEFT:
                    likeLeft(column, value);
                    break;
                case NOT_LIKE_LEFT:
                    notLikeLeft(column, value);
                    break;
                case LIKE_RIGHT:
                    likeRight(column, value);
                    break;
                case NOT_LIKE_RIGHT:
                    notLikeRight(column, value);
                    break;
                case IS_NULL:
                    isNull(column);
                    break;
                case IS_NOT_NULL:
                    isNotNull(column);
                    break;
                case OR:
                    or();
                    break;
                case OR_BUILD:
                    orBuild((Consumer<SqlInfoConditionModel.Builder>) value[0]);
                    break;
                case AND_BUILD:
                    andBuild((Consumer<SqlInfoConditionModel.Builder>) value[0]);
                    break;
                case APPLY:
                    apply(column);
                    break;
            }
        });
        String sqlStr = "";

        if(conditionModel instanceof SqlInfoHavingModel){
            sqlStr=wrapper.getHavingCustomSqlSegment();
        }else{
            sqlStr=wrapper.getCustomSqlSegment();
        }
        Map<String, Object> paramNameValuePairs = wrapper.getParamNameValuePairs();

        SqlFormatModel sqlFormatModel = new SqlFormatModel(sqlStr, paramNameValuePairs);
        return sqlFormatModel;
    }

    public void gt(String column, Object[] value) {
        wrapper.gt(column, value[0]);
        return;
    }

    public void ge(String column, Object[] value) {
        wrapper.ge(column, value[0]);
        return;
    }

    public void ne(String column, Object[] value) {
        wrapper.ne(column, value[0]);
        return;
    }

    public void eq(String column, Object[] value) {
        wrapper.eq(column, value[0]);
        return;
    }

    public void between(String column, Object[] value) {
        Object value1=value[0];
        Object value2=value[1];
        wrapper.between(column, value1, value2);
        return;
    }

    public void notbetween(String column,Object[] value) {
        Object value1=value[0];
        Object value2=value[1];
        wrapper.notBetween(column, value1, value2);
        return;
    }

    public void in(String column, Object[] value) {
        if(value.length>1){
            wrapper.in(column, value);
            return;
        }
        Object obj = value[0];
        if(obj instanceof List){
            List<Object> objList=(List)value[0];
            wrapper.in(column, objList);
        }else{
            wrapper.in(column, obj);
        }
        return;
    }

    public void notIn(String column, Object[] value) {
        if(value.length>1){
            wrapper.notIn(column, value);
            return;
        }
        Object obj = value[0];
        if(obj instanceof List){
            List<Object> objList=(List)value[0];
            wrapper.notIn(column, objList);
        }else{
            wrapper.notIn(column, obj);
        }
        return;
    }

    public void like(String column, Object[] value) {
        wrapper.like(column, value[0]);
        return;
    }

    public void notLike(String column, Object[] value) {
        wrapper.notLike(column, value[0]);
        return;
    }

    public void likeLeft(String column, Object[] value) {
        wrapper.likeLeft(column, value[0]);
        return;
    }
    public void notLikeLeft(String column, Object[] value) {
        wrapper.notLikeLeft(column, value[0]);
        return;
    }

    public void likeRight(String column, Object[] value) {
        wrapper.likeRight(column, value[0]);
        return;
    }
    public void notLikeRight(String column, Object[] value) {
        wrapper.notLikeRight(column, value[0]);
        return;
    }

    public void lt(String column, Object[] value) {
        wrapper.lt(column, value[0]);
        return;
    }

    public void le(String column, Object[] value) {
        wrapper.le(column, value[0]);
        return;
    }

    public void isNull(String column) {
        wrapper.isNull(column);
        return;
    }

    public void isNotNull(String column) {
        wrapper.isNotNull(column);
        return;
    }
    public void apply(String column) {
        wrapper.apply(column);
        return;
    }
    public void or() {
        wrapper.or();
        return;
    }


    public void orBuild(Consumer<SqlInfoConditionModel.Builder> condition) {
        try{
            SqlInfoConditionModel.Builder builder = new SqlInfoConditionModel.Builder();
            condition.accept(builder);
            SqlInfoConditionModel<BuildCondition> build = builder.build();
            BuildCondition buildCondition =  new BuildCondition();
            SqlFormatModel sqlFormatModel = buildCondition.context2Condition(build);

            String tmpSql = sqlFormatModel.getSql();
            tmpSql=tmpSql.substring(6);
            Map<String, Object> tmpMap = sqlFormatModel.getDataMap();
            if (FuncBase.isEmpty(tmpMap)) {//没有参数的情况下
                String newSql=String.format("( 1!=1 OR %s) ",tmpSql);
                wrapper.apply(newSql);
                return;
            }

            //存在参数的情况下
            List<Map.Entry<String, Object>> entrieList = new ArrayList<>(tmpMap.entrySet());
            Collections.reverse(entrieList);

            int step=0;
            Object[] objects=new Object[entrieList.size()];

            // 然后，从列表的末尾开始遍历
            for (Map.Entry<String, Object> entry : entrieList) {
                String key = entry.getKey(); // 获取键
                Object value = entry.getValue(); // 获取值

                // 执行你的替换逻辑
                tmpSql = tmpSql.replace("#{"+ FuncBase.PARAM_NAME_VALUE_PAIRS+"." + key + "}", "{"+step+"}");
                objects[step]=value;

                step++;
            }
            String newSql=String.format(" ( 1!=1 OR %s) ",tmpSql);//1!=1 兼容语法
            wrapper.apply(newSql,objects);
        }catch (Exception e){

        }

        return;
    }

    public void andBuild(Consumer<SqlInfoConditionModel.Builder> condition) {
        try{

            SqlInfoConditionModel.Builder builder = new SqlInfoConditionModel.Builder();
            condition.accept(builder);
            SqlInfoConditionModel<BuildCondition> build = builder.build();
            BuildCondition buildCondition =  new BuildCondition();
            SqlFormatModel sqlFormatModel = buildCondition.context2Condition(build);

            String tmpSql = sqlFormatModel.getSql();
            tmpSql=tmpSql.substring(6);
            Map<String, Object> tmpMap = sqlFormatModel.getDataMap();
            if (FuncBase.isEmpty(tmpMap)) {//没有参数的情况下
                String newSql=String.format("(%s) ",tmpSql);
                wrapper.apply(newSql);
                return;
            }

            //存在参数的情况下
            List<Map.Entry<String, Object>> entrieList = new ArrayList<>(tmpMap.entrySet());
            Collections.reverse(entrieList);

            int step=0;
            Object[] objects=new Object[entrieList.size()];

            // 然后，从列表的末尾开始遍历
            for (Map.Entry<String, Object> entry : entrieList) {
                String key = entry.getKey(); // 获取键
                Object value = entry.getValue(); // 获取值

                // 执行你的替换逻辑
                tmpSql = tmpSql.replace("#{"+ FuncBase.PARAM_NAME_VALUE_PAIRS+"." + key + "}", "{"+step+"}");

                objects[step]=value;

                step++;
            }
            String newSql=String.format(" (%s) ",tmpSql);
            wrapper.apply(newSql,objects);
        }catch (Exception e){

        }

        return;
    }

    public lideeYunJiQueryWrapper<Object> getWrapper() {
        return wrapper;
    }

    public void setWrapper(lideeYunJiQueryWrapper<Object> wrapper) {
        this.wrapper = wrapper;
    }

    public SQLInterpretContext getContext() {
        return this.context;
    }

    public void setContext(SQLInterpretContext context) {
        this.context = context;
    }
}
