package com.lideeyunji.tool.framework.sql;


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.ddl.*;
import com.lideeyunji.tool.framework.sql.build.build.dql.BuildSelect;
import com.lideeyunji.tool.framework.sql.build.buildmodel.SQLInterpretContext;
import com.lideeyunji.tool.framework.sql.build.buildmodel.ddl.*;
import com.lideeyunji.tool.framework.sql.build.buildmodel.dql.SqlInfoPublicModel;
import com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper.SqlInfoDeleteWrapper;
import com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper.SqlInfoInsertWrapper;
import com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper.SqlInfoQueryWrapper;
import com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper.SqlInfoUpdateWrapper;
import com.lideeyunji.tool.framework.sql.chain.entity.TenantIdFilterEntity;
import com.lideeyunji.tool.framework.sql.entity.DbColunmTypesEntity;
import com.lideeyunji.tool.framework.sql.entity.FieldModel;
import com.lideeyunji.tool.framework.sql.entity.SqlInfoEntity;
import com.lideeyunji.tool.framework.sql.enums.DbTypeEnum;
import com.lideeyunji.tool.framework.sql.flyweight.FlyweightDBFactory;
import com.lideeyunji.tool.framework.sql.template.AbstractDbTemplate;
import com.lideeyunji.tool.framework.sql.core.model.SqlFormatModel;
import com.lideeyunji.tool.framework.yunji.adapter.IlideeYunjiAdapter;
import com.lideeyunji.tool.framework.yunji.enums.YNEnum;
import com.lideeyunji.tool.framework.yunji.tool.spring.SpringUtils;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
import net.sf.jsqlparser.JSQLParserException;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SqlHelper {

    //数据库类型
    //private static String dbType="postgresql";
    //private static String dbSchemaName="db_lideeyunji";

    private static String dbType="mysql";
    private static String dbSchemaName="db_lideeyunji";

    //数据库类型
    //private static String dbType="oracle";
    //private static String dbSchemaName="c##jee_test";

    public static void setDbType(String dbType) {
        SqlHelper.dbType = dbType;
    }


    public static void setDbSchemaName(String dbSchemaName) {
        SqlHelper.dbSchemaName = dbSchemaName;
    }

    private static AbstractDbTemplate getAbstractDbTemplate() {
        DbTypeEnum dbTypeEnum = DbTypeEnum.getByDbCode(dbType);
        AbstractDbTemplate template = FlyweightDBFactory.getDbType(dbTypeEnum);
        return template;
    }

    public static DbColunmTypesEntity getDbColunmTypesEntity() {
        DbTypeEnum dbTypeEnum = DbTypeEnum.getByDbCode(dbType);
        AbstractDbTemplate template = FlyweightDBFactory.getDbType(dbTypeEnum);

        SqlInfoEntity sqlInfoEntity=new SqlInfoEntity();
        SQLInterpretContext context =new SQLInterpretContext(dbSchemaName);
        sqlInfoEntity.setContext(context);
        template.operation(sqlInfoEntity);
        return sqlInfoEntity.getContext().getDbColunmTypes();
    }

    public static DbTypeEnum getDbTypeEnum(){
        DbTypeEnum dbTypeEnum = DbTypeEnum.getByDbCode(dbType);
        return dbTypeEnum;
    }

    //获取租户权限
    private static TenantIdFilterEntity getTenantIdFilterEntity() {
        //处理租户
        IlideeYunjiAdapter adapter = SpringUtils.getBean(IlideeYunjiAdapter.class);


        TenantIdFilterEntity tenantIdFilterEntity = new TenantIdFilterEntity();
        tenantIdFilterEntity.setTenantId(adapter.getTenantId());
        return tenantIdFilterEntity;
    }

    //新建表
    public static List<String> createTable(String tableName, String tableAlias, List<FieldModel> fieldModelList) throws JSQLParserException {
        /**
         * 创建表分三步
         * 1.创建简单表  id varchar(10) not null
         * 2.处理备注
         * 3.处理主键
         */
        //1.创建表
        SqlInfoCreateModel<BuildCreateTable> createModel = SqlInfoCreateModel.builder()
                .setTableName(tableName)
                .setTableOptions(fieldModelList)
                .build();

        //2.处理字段备注
        SqlInfoCommentModel<BuildComment> commentmodel = SqlInfoCommentModel.builder()
                .setTableName(tableName)
                .setTableAlias(tableAlias)
                .setfieldModelList(fieldModelList)
                .build();
        //3.处理主键
        List<String> primaryKeyList = fieldModelList.stream()
                .filter(fieldModel -> !FuncBase.isEmpty(fieldModel.getIsPrimaryKey()) && !FuncBase.equals(fieldModel.getIsPrimaryKey(), YNEnum.N.getCode()))
                .map(FieldModel::getFieldCode)
                .collect(Collectors.toList());
        //3.处理主键
        SqlInfoPrimaryKeyModel primaryKeyModel = SqlInfoPrimaryKeyModel.builder()
                .setTableName(tableName)
                .setPrimaryKey(primaryKeyList)
                .build();

        //构建SQL上下文
        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setCreateModel(createModel);
        context.setCommentModel(commentmodel);
        context.setPrimaryKeyModel(primaryKeyModel);

        //多个
        AndExpression expression = new AndExpression(createModel.getSqlExpression(), commentmodel.getSqlExpression(),primaryKeyModel.getSqlExpression());
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, expression);

        List<String> ddlList = sqlFormatModelList.stream()
                .map(SqlFormatModel::getSql)
                .collect(Collectors.toList());
        return ddlList;
    }

    //增加列
    public static List<String> addColumn(String tableName, FieldModel fieldModel) {
        /**
         * 增加列分两步
         * 1.创建简单表
         * 2.处理备注
         */

        //1.创建表
        SqlInfoAlterModel<BuildAlter> addColumnModel = SqlInfoAlterModel.builder()
                .setTableName(tableName)
                .buildAddColumn(fieldModel);

        //2.处理主键
        SqlInfoPrimaryKeyModel primaryKeyModel =null;
        if(FuncBase.equals(fieldModel.getFieldCode(),"id")){
            primaryKeyModel = SqlInfoPrimaryKeyModel.builder()
                    .setTableName(tableName)
                    .setPrimaryKey(FuncBase.toStrList("id"))
                    .build();
        }




        List<FieldModel> fieldModelList = new ArrayList<>();
        fieldModelList.add(fieldModel);

        SqlInfoCommentModel<BuildComment> commentmodel = SqlInfoCommentModel.builder()
                .setTableName(tableName)
                .setfieldModelList(fieldModelList)
                .build();

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setAlterModel(addColumnModel);
        context.setCommentModel(commentmodel);
        context.setPrimaryKeyModel(primaryKeyModel);//主键

        //多个
        AndExpression expression =null;
        if(FuncBase.isNotEmpty(context.getPrimaryKeyModel())){
            expression = new AndExpression(addColumnModel.getSqlExpression(), commentmodel.getSqlExpression(),primaryKeyModel.getSqlExpression());
        }else{
            expression = new AndExpression(addColumnModel.getSqlExpression(), commentmodel.getSqlExpression());
        }

        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, expression);

        List<String> ddlList = sqlFormatModelList.stream()
                .map(SqlFormatModel::getSql)
                .collect(Collectors.toList());
        return ddlList;
    }

    //修改列
    public static List<String> modifyColumnSql(String tableName, FieldModel fieldModel) {
        /**
         * 增加列分两步
         * 1.创建简单表
         * 2.处理备注
         */
        //修改表
        SqlInfoAlterModel<BuildAlter> modifyColumnModel = SqlInfoAlterModel.builder()
                .setTableName(tableName)
                .buildUpdateColum(fieldModel);

        List<FieldModel> fieldModelList = new ArrayList<>();
        fieldModelList.add(fieldModel);

        SqlInfoCommentModel<BuildComment> commentModel = SqlInfoCommentModel.builder()
                .setTableName(tableName)
                .setfieldModelList(fieldModelList)
                .build();

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setAlterModel(modifyColumnModel);
        context.setCommentModel(commentModel);

        //多个
        AndExpression expression = new AndExpression(modifyColumnModel.getSqlExpression(), commentModel.getSqlExpression());
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, expression);

        List<String> ddlList = sqlFormatModelList.stream()
                .map(SqlFormatModel::getSql)
                .collect(Collectors.toList());
        return ddlList;
    }

    //删除列
    public static String getDropColumnSql(String tableName,String clumn) {
        SqlInfoDropModel<BuildDrop> dropModel = SqlInfoDropModel.builder()
                .buildDropColumn(tableName, clumn);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDropModel(dropModel);

        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, dropModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //删除表
    public static String getDropTableSql(String tableName) {
        SqlInfoDropModel<BuildDrop> dropTableModel = SqlInfoDropModel.builder()
                .buildDropTable(tableName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDropModel(dropTableModel);

        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, dropTableModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //创建索引
    public static String createIndex(String tableName,String indexName,String indexType,List<String> fieldList) {

        SqlInfoCreateIndexModel<BuildCreateIndex> createIndexModel = SqlInfoCreateIndexModel.builder()
                .setTableName(tableName)
                .setIndexName(indexName)
                .setIndexType(indexType)
                .setIndexFieldCodeList(fieldList)
                .build();

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setCreateIndexModel(createIndexModel);

        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, createIndexModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //删除索引
    public static String getDropIndex(String tableName,String indexName) {

        SqlInfoDropModel<BuildDrop> dropModel = SqlInfoDropModel.builder()
                .buildDropIndex(tableName, indexName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDropModel(dropModel);

        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, dropModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //校验索引是否存在
    public static String getIndexExistSql(String tableName,String  indexName){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildIndexExist(tableName, indexName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //获取某一个表所有索引
    public static String getIndexAllByTableSql(String tableName){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildIndexAllByTable(tableName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //校验表是否存在
    public static String getTableExistSql(String tableName){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildTableExist(tableName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //校验表是否存在
    public static String getAllTableNameSql(){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildGetAllTableName();

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //获取表字段备注
    public static String getTableFieldComment(String tableName){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildFieldComment(tableName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //获取表备注
    public static String getTableComment(String tableName){
        SqlInfoDdlModel<BuildDdl> ddlModel = SqlInfoDdlModel.builder().buildTableComment(tableName);

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setDdlModel(ddlModel);
        List<SqlFormatModel> sqlFormatModelList = ddlExpression(context, ddlModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //--------------dql---------------
    //通用sql
    public static String getPublicSql(String sql){
        SqlInfoPublicModel<BuildSelect> publicModel = SqlInfoPublicModel.builder().setSql(sql).build();

        SQLInterpretContext context = new SQLInterpretContext(dbSchemaName);
        context.setPublicModel(publicModel);
        List<SqlFormatModel> sqlFormatModelList = sqlExpression(context, publicModel.getSqlExpression());
        return sqlFormatModelList.get(0).getSql();
    }

    //查询数据
    public static SqlInfoQueryWrapper.Wrapper getQueryWrapper(){
        SqlInfoQueryWrapper.Wrapper wrapper = SqlInfoQueryWrapper.wrapper(dbSchemaName);
        return wrapper;
    }

    //新增数据
    public static SqlInfoInsertWrapper.Wrapper getInsertWrapper(){
        SqlInfoInsertWrapper.Wrapper wrapper = SqlInfoInsertWrapper.wrapper(dbSchemaName);
        return wrapper;
    }

    //修改数据
    public static SqlInfoUpdateWrapper.Wrapper getUpdateWrapper(){
        SqlInfoUpdateWrapper.Wrapper wrapper = SqlInfoUpdateWrapper.wrapper(dbSchemaName);
        return wrapper;
    }

    //删除数据
    public static SqlInfoDeleteWrapper.Wrapper getDeleteWrapper(){
        SqlInfoDeleteWrapper.Wrapper wrapper = SqlInfoDeleteWrapper.wrapper(dbSchemaName);
        return wrapper;
    }



    //自定义 sql
    public static List<SqlFormatModel> sqlExpression(SQLInterpretContext context, ISQLExpression expression) {
        Boolean tenantIgnore = context.getTenantIgnore();
        TenantIdFilterEntity tenantIdFilterEntity =null;
        if(FuncBase.isEmpty(tenantIgnore) || !tenantIgnore){//不做多租户处理
             tenantIdFilterEntity =getTenantIdFilterEntity();
        }
        SqlInfoEntity sqlInfoEntity = new SqlInfoEntity();
        List<SqlFormatModel> sqlModelList = sqlExpression(sqlInfoEntity,context, expression, tenantIdFilterEntity);
        return sqlModelList;
    }
    //自定义 ddl
    public static List<SqlFormatModel> ddlExpression(SQLInterpretContext context, ISQLExpression expression) {
        SqlInfoEntity sqlInfoEntity = new SqlInfoEntity();
        List<SqlFormatModel> sqlModelList = sqlExpression(sqlInfoEntity,context, expression, null);
        return sqlModelList;
    }
    //自定义 只需要使用sql解析
    public static List<SqlFormatModel> parserExpression(SQLInterpretContext context, ISQLExpression expression) {
        SqlInfoEntity sqlInfoEntity = new SqlInfoEntity();
        sqlInfoEntity.setSqlParserLevel(2);
        List<SqlFormatModel> sqlModelList = sqlExpression(sqlInfoEntity,context, expression, null);
        return sqlModelList;
    }

    private static List<SqlFormatModel> sqlExpression(SqlInfoEntity sqlInfoEntity,SQLInterpretContext context, ISQLExpression expression, TenantIdFilterEntity tenantIdFilterEntity) {
        AbstractDbTemplate template = getAbstractDbTemplate();

        sqlInfoEntity.setContext(context);
        sqlInfoEntity.setSqlExpression(expression);
        if (FuncBase.isNotEmpty(tenantIdFilterEntity)) {
            sqlInfoEntity.setTenantIdFilterEntity(tenantIdFilterEntity);
        }

        template.operation(sqlInfoEntity);
        List<SqlFormatModel> sqlModelList = sqlInfoEntity.getSqlModelList();
        if (FuncBase.isEmpty(sqlModelList)) {
            return sqlModelList;
        }
        sqlModelList.forEach(model->{
            String sql = model.getSql();
            if(sql.endsWith(";")){
                System.out.println(sql);
            }else{
                System.out.println(sql+";");
            }
        });
        return sqlModelList;
    }


}
