
package com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper;

import com.lideeyunji.tool.framework.sql.SqlHelper;
import com.lideeyunji.tool.framework.sql.build.ISQLExpression;
import com.lideeyunji.tool.framework.sql.build.build.AndExpression;
import com.lideeyunji.tool.framework.sql.build.build.dql.*;
import com.lideeyunji.tool.framework.sql.build.buildmodel.SQLInterpretContext;
import com.lideeyunji.tool.framework.sql.build.buildmodel.dql.*;
import com.lideeyunji.tool.framework.sql.core.model.SqlFormatModel;
import com.lideeyunji.tool.framework.yunji.constant.lideeYunjiCodeConstant;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;

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

/**
 * 查询-封装器
 */
public class SqlInfoQueryWrapper {


    public static Wrapper wrapper(String dbSchemaName) {
        return new Wrapper(dbSchemaName);
    }

    public static class Wrapper extends BaseWrapper {

        private String dataSourceType;//指定数据源

        private Boolean tenantIgnore;//本次是否忽略租户

        private String dbSchemaName;
        private SqlInfoSelectModel.Builder builderSelect = SqlInfoSelectModel.builder();
        private SqlInfoWhereModel.Builder builderWhere = SqlInfoWhereModel.builder();
        private SqlInfoOrderModel.Builder builderOrderBy = SqlInfoOrderModel.builder();
        private SqlInfoGroupModel.Builder builderGroupBy = SqlInfoGroupModel.builder();
        private SqlInfoHavingModel.Builder builderHaving = SqlInfoHavingModel.builder();
        private SqlInfoJoinModel.Builder builderJoin = SqlInfoJoinModel.builder();

        public Wrapper(String dbSchemaName) {
            this.dbSchemaName = dbSchemaName;
        }

        public Wrapper setTenantIgnore(Boolean tenantIgnore) {
            this.tenantIgnore=tenantIgnore;//本次是否忽略租户
            return this;
        }

        public Wrapper setDataSourceType(String dataSourceType) {
            this.dataSourceType=dataSourceType;//外部数据源
            return this;
        }

        public String getDataSourceType() {
            return this.dataSourceType;
        }

        //select 相关
        public Wrapper select(String... columns) {
            if (FuncBase.isNotEmpty(columns)) {
                builderSelect.setColumns(columns);
                initSet.add(BUILDER_SELECT);
            }
            return this;
        }

        public Wrapper select(List<String> columnsList, boolean aliasFlag) {
            if (FuncBase.isNotEmpty(columnsList)) {
                //处理别名
                if (aliasFlag) {
                    columnsList = FuncBase.fieldCodeAlias(columnsList);
                }

                builderSelect.setColumns(columnsList.toArray(new String[0]));
                initSet.add(BUILDER_SELECT);
            }
            return this;
        }

        public Wrapper setTableName(String tableName) {
            //处理别名
            builderSelect.setTableName(tableName, lideeYunjiCodeConstant.TABLE_ALIAS);
            initSet.add(BUILDER_SELECT);
            return this;
        }

        public Wrapper setTableSql(String tableNameSql) {
            //处理别名
            String sql = String.format("(%s)", tableNameSql);
            builderSelect.setTableName(sql, lideeYunjiCodeConstant.TABLE_ALIAS);
            initSet.add(BUILDER_SELECT);
            return this;
        }

        //where 相关
        public Wrapper setWhere(Consumer<SqlInfoWhereModel.Builder> whereBuilderConsumer) {
            whereBuilderConsumer.accept(builderWhere);
            initSet.add(BUILDER_WHERE);
            return this;
        }

        //order by相关
        public Wrapper orderByAsc(String... columns) {
            builderOrderBy.setOrderByAsc(columns);
            initSet.add(BUILDER_ORDERBY);
            return this;
        }

        public Wrapper orderByDesc(String... columns) {
            builderOrderBy.setOrderByDesc(columns);
            initSet.add(BUILDER_ORDERBY);
            return this;
        }

        //group by 相关
        public Wrapper groupByColumns(String... columns) {
            builderGroupBy.setColumns(columns);
            initSet.add(BUILDER_GROUPBY);
            return this;
        }

        //join 相关
        public Wrapper joinByinnerJoinTable(String tableName, String alias) {
            builderJoin.joinTable(tableName, alias);
            builderJoin.innerJoin();
            initSet.add(BUILDER_JOIN);
            return this;
        }

        public Wrapper joinByleftJoinTable(String tableName, String alias) {
            builderJoin.joinTable(tableName, alias);
            builderJoin.leftJoin();
            initSet.add(BUILDER_JOIN);
            return this;
        }

        public Wrapper joinByrightJoinTable(String tableName, String alias) {
            builderJoin.joinTable(tableName, alias);
            builderJoin.rightJoin();
            initSet.add(BUILDER_JOIN);
            return this;
        }

        public Wrapper joinOn(String leftStr, String rightStr) {
            builderJoin.on(leftStr, rightStr);
            initSet.add(BUILDER_JOIN);
            return this;
        }

        //构建having
        public Wrapper setHaving(Consumer<SqlInfoHavingModel.Builder> havingBuilderConsumer) {
            havingBuilderConsumer.accept(builderHaving);
            initSet.add(BUILDER_HAVING);
            return this;
        }

        public Wrapper build() {
            return this;
        }

        public SqlFormatModel buildSql() {
            SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
            SqlInfoSelectModel<BuildSelect> buildSelect = builderSelect.build();
            SqlInfoWhereModel<BuildWhere> buildWhere = builderWhere.buildWhere();
            SqlInfoOrderModel<BuildOrderBy> buildOrderBy = builderOrderBy.build();
            SqlInfoGroupModel<BuildDelete> buildGroupBy = builderGroupBy.build();
            SqlInfoJoinModel<SqlFormatModel> buildJoin = builderJoin.build();
            SqlInfoHavingModel<BuildHaving> buildHaving = builderHaving.buildHaving();

            //本次是否忽略租户
            if(FuncBase.isNotEmpty(tenantIgnore)){
                context.setTenantIgnore(tenantIgnore);
            }

            List<ISQLExpression> expressionList = new ArrayList<>();
            if (initSet.contains(BUILDER_SELECT)) {
                context.setSelectModel(buildSelect);
                expressionList.add(new BuildSelect());
            }
            if (initSet.contains(BUILDER_WHERE)) {
                context.setWhereModel(buildWhere);
                expressionList.add(new BuildWhere());
            }
            if (initSet.contains(BUILDER_ORDERBY)) {
                context.setOrderModel(buildOrderBy);
                expressionList.add(new BuildOrderBy());
            }
            if (initSet.contains(BUILDER_GROUPBY)) {
                context.setGroupModel(buildGroupBy);
                expressionList.add(new BuildGroupBy());
            }
            if (initSet.contains(BUILDER_JOIN)) {
                context.setJoinModel(buildJoin);
                expressionList.add(new BuildJoin());
            }
            if (initSet.contains(BUILDER_HAVING)) {
                context.setHavingModel(buildHaving);
                expressionList.add(new BuildHaving());
            }

            if(FuncBase.isEmpty(expressionList)){
                return new SqlFormatModel();
            }
            List<SqlFormatModel> sqlFormatModelList = null;

            ISQLExpression expression = new AndExpression(expressionList);
            if (initSet.contains(BUILDER_SELECT)) {
                sqlFormatModelList = SqlHelper.sqlExpression(context, expression);
            } else {
                sqlFormatModelList = SqlHelper.parserExpression(context, expression);
            }

            return sqlFormatModelList.get(0);
        }
    }


}
