package cn.stylefeng.team.meta.modular.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.generator.api.CodeGeneratorApi;
import cn.stylefeng.team.generator.api.TemplateGetApi;
import cn.stylefeng.team.generator.api.enums.GeneratorTypeEnum;
import cn.stylefeng.team.generator.api.pojo.generator.result.CommonGenerateResult;
import cn.stylefeng.team.generator.api.pojo.template.GeneratorTemplateGroup;
import cn.stylefeng.team.meta.api.DatabaseMetadataApi;
import cn.stylefeng.team.meta.api.entity.MetaDefinition;
import cn.stylefeng.team.meta.api.entity.MetaField;
import cn.stylefeng.team.meta.api.entity.MetaModel;
import cn.stylefeng.team.meta.api.enums.MetaModelTypeEnum;
import cn.stylefeng.team.meta.api.pojo.MetaFieldDTO;
import cn.stylefeng.team.meta.api.pojo.MetaModelCreatSqlDTO;
import cn.stylefeng.team.meta.api.pojo.MetaModelDTO;
import cn.stylefeng.team.meta.api.pojo.db.DatabaseMetadataRequest;
import cn.stylefeng.team.meta.api.pojo.db.TableDescription;
import cn.stylefeng.team.meta.api.pojo.table.GenerationTableAlter;
import cn.stylefeng.team.meta.api.pojo.table.TableAlterLog;
import cn.stylefeng.team.meta.modular.context.DatabaseConnectionContext;
import cn.stylefeng.team.meta.modular.enums.MetaDefinitionExceptionEnum;
import cn.stylefeng.team.meta.modular.enums.MetaModelExceptionEnum;
import cn.stylefeng.team.meta.modular.factory.FieldFactory;
import cn.stylefeng.team.meta.modular.factory.MetaModelFactory;
import cn.stylefeng.team.meta.modular.factory.ModelDefinitionFactory;
import cn.stylefeng.team.meta.modular.pojo.CategoryInfo;
import cn.stylefeng.team.meta.modular.pojo.request.MetaModelRequest;
import cn.stylefeng.team.meta.modular.pojo.request.TableUpdateOperateRequest;
import cn.stylefeng.team.meta.modular.service.CreateTableGenerateService;
import cn.stylefeng.team.meta.modular.service.MetaDefinitionService;
import cn.stylefeng.team.meta.modular.service.MetaFieldService;
import cn.stylefeng.team.meta.modular.service.MetaModelService;
import cn.stylefeng.team.meta.modular.service.common.BaseMetaModelService;
import cn.stylefeng.team.project.api.BusinessCategoryApi;
import cn.stylefeng.team.project.api.SystemCodeApi;
import cn.stylefeng.team.project.api.entity.BusinessCategory;
import cn.stylefeng.team.project.api.enums.SystemCodeTypeEnum;
import cn.stylefeng.team.project.api.exception.enums.ProjectExceptionEnum;
import cn.stylefeng.team.project.api.pojo.SystemCodeInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MetaModelServiceImpl extends BaseMetaModelService implements MetaModelService {

    @Resource
    private MetaDefinitionService metaDefinitionService;

    @Resource
    private MetaFieldService metaFieldService;

    @Resource
    private SystemCodeApi systemCodeApi;

    @Resource
    private TemplateGetApi templateGetApi;

    @Resource
    private CreateTableGenerateService createTableGenerateService;

    @Resource
    private DatabaseMetadataApi databaseMetadataApi;

    @Resource
    private BusinessCategoryApi businessCategoryApi;

    @Resource
    private CodeGeneratorApi codeGeneratorApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(MetaModelRequest metaModelRequest) {

        this.validateRepeat(metaModelRequest, false);

        systemCodeApi.validateSystemCodeShow(SystemCodeTypeEnum.MODEL, metaModelRequest.getSystemCode(), metaModelRequest.getSystemCodeShow());

        MetaModelFactory.commonAddModel(metaModelRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(MetaModelRequest metaModelRequest) {

        MetaModel metaModel = this.queryMetaModel(metaModelRequest);

        this.removeById(metaModel.getMetaModelId());

        List<Long> definitionIdList = this.metaDefinitionService.removeDefinitionList(metaModel.getMetaModelId());

        this.metaFieldService.removeDefinitionFieldList(definitionIdList);

    }

    @Override
    public void edit(MetaModelRequest metaModelRequest) {

        this.validateRepeat(metaModelRequest, true);

        MetaModel metaModel = this.queryMetaModel(metaModelRequest);

        metaModel.setMetaModelName(metaModelRequest.getMetaModelName());
        metaModel.setMetaModelCode(metaModelRequest.getMetaModelCode());
        metaModel.setMainFlag(metaModelRequest.getMainFlag());
        metaModel.setSubTableFieldCode(metaModelRequest.getSubTableFieldCode());
        metaModel.setSubTableType(metaModelRequest.getSubTableType());
        metaModel.setDescription(metaModelRequest.getDescription());
        metaModel.setFldSort(metaModelRequest.getFldSort());

        this.updateById(metaModel);
    }

    @Override
    public MetaModel detail(MetaModelRequest metaModelRequest) {
        return this.queryMetaModel(metaModelRequest);
    }

    @Override
    public PageResult<MetaModel> findPage(MetaModelRequest metaModelRequest) {
        LambdaQueryWrapper<MetaModel> wrapper = createWrapper(metaModelRequest);

        wrapper.select(MetaModel::getMetaModelId, MetaModel::getCurrentDefinitionId, MetaModel::getMetaModelName, MetaModel::getMetaModelCode, MetaModel::getMetaModelType, MetaModel::getLinkModelId,
                MetaModel::getSystemCodeShow, MetaModel::getFldSort, BaseEntity::getCreateTime, MetaModel::getMainFlag);

        Page<MetaModel> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);
        List<MetaModel> records = sysRolePage.getRecords();
        if (ObjectUtil.isNotEmpty(records)) {

            DatabaseMetadataRequest databaseMetadataRequest = DatabaseConnectionContext.currentDatabaseInfo();
            List<TableDescription> tableNameList = databaseMetadataApi.getTableNameList(databaseMetadataRequest);

            for (MetaModel record : records) {
                for (TableDescription tableDescription : tableNameList) {
                    if (record.getMetaModelCode().equalsIgnoreCase(tableDescription.getTableCode())) {
                        record.setTableCreateFlag(true);
                        break;
                    }
                }
            }
        }

        return PageResultFactory.createPageResult(sysRolePage);
    }

    @Override
    public void updateModelVersion(MetaDefinition newMetaDefinition) {
        Long metaModelId = newMetaDefinition.getMetaModelId();

        LambdaUpdateWrapper<MetaModel> metaModelLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        metaModelLambdaUpdateWrapper.set(MetaModel::getCurrentVersion, newMetaDefinition.getFldVersion());
        metaModelLambdaUpdateWrapper.set(MetaModel::getCurrentDefinitionId, newMetaDefinition.getMetaDefinitionId());
        metaModelLambdaUpdateWrapper.eq(MetaModel::getMetaModelId, metaModelId);
        this.update(metaModelLambdaUpdateWrapper);
    }

    @Override
    public List<MetaModel> findList(MetaModelRequest metaModelRequest) {

        LambdaQueryWrapper<MetaModel> wrapper = this.createWrapper(metaModelRequest);

        wrapper.select(MetaModel::getMetaModelId, MetaModel::getCurrentDefinitionId,
                MetaModel::getMetaModelName, MetaModel::getMetaModelCode, MetaModel::getBusinessCategoryId);

        List<MetaModel> list = this.list(wrapper);

        if (ObjectUtil.isNotEmpty(list) && metaModelRequest.getFindSubFlag() != null && metaModelRequest.getFindSubFlag()) {
            list.remove(0);
        }

        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MetaDefinition quickAddModelAndDefinition(Long businessCategoryId, Long businessId, String metaModelName, String metaModelCode) {

        MetaModelRequest metaModelRequest = new MetaModelRequest();

        if (StrUtil.isBlank(metaModelName)) {
            metaModelRequest.setMetaModelName("未命名模型");
        } else {
            metaModelRequest.setMetaModelName(metaModelName);
        }

        if (StrUtil.isBlank(metaModelCode)) {
            metaModelRequest.setMetaModelCode("null_model_code");
        } else {
            metaModelRequest.setMetaModelCode(metaModelCode);
        }

        MetaModel metaModel = this.validateCodeRepeat(metaModelRequest);
        if (metaModel != null) {
            MetaModelRequest tempRequest = new MetaModelRequest();
            tempRequest.setMetaModelId(metaModel.getMetaModelId());
            return this.upgradeModel(tempRequest);
        }

        SystemCodeInfo newSystemCode = systemCodeApi.createNewSystemCode(SystemCodeTypeEnum.MODEL);
        metaModelRequest.setSystemCode(newSystemCode.getSystemCode());
        metaModelRequest.setSystemCodeShow(newSystemCode.getSystemCodeShow());

        metaModelRequest.setBusinessCategoryId(businessCategoryId);
        metaModelRequest.setBusinessId(businessId);

        return MetaModelFactory.commonAddModel(metaModelRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(MetaModelRequest metaModelRequest) {

        for (Long metaModelId : metaModelRequest.getBatchDeleteIdList()) {
            MetaModelRequest tempRequest = new MetaModelRequest();
            tempRequest.setMetaModelId(metaModelId);
            this.del(tempRequest);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MetaDefinition upgradeModel(MetaModelRequest metaModelRequest) {

        MetaModel metaModel = this.queryMetaModel(metaModelRequest);

        MetaDefinition oldDefinition = metaDefinitionService.findModelNewestDefinition(metaModel.getMetaModelId());

        List<MetaField> oldMetaFieldList = metaFieldService.quickGetFieldList(oldDefinition.getMetaDefinitionId());
        if (ObjectUtil.isEmpty(oldMetaFieldList)) {
            MetaDefinition returnDefinition = new MetaDefinition();
            returnDefinition.setMetaModelId(oldDefinition.getMetaModelId());
            returnDefinition.setMetaDefinitionId(oldDefinition.getMetaDefinitionId());
            return returnDefinition;
        }

        MetaDefinition newDefinition = ModelDefinitionFactory.upgradeDefinition(oldDefinition);

        List<MetaField> newMetaFieldList = FieldFactory.createMetaField(newDefinition, oldMetaFieldList);

        metaModel.setCurrentVersion(newDefinition.getFldVersion());
        metaModel.setCurrentDefinitionId(newDefinition.getMetaDefinitionId());
        this.updateById(metaModel);

        metaDefinitionService.save(newDefinition);

        this.metaFieldService.customBatchSave(newMetaFieldList);

        MetaDefinition returnDefinition = new MetaDefinition();
        returnDefinition.setMetaModelId(newDefinition.getMetaModelId());
        returnDefinition.setMetaDefinitionId(newDefinition.getMetaDefinitionId());
        return returnDefinition;
    }

    @Override
    public String getMetaModelNameById(Long metaModelId) {

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.eq(MetaModel::getMetaModelId, metaModelId);
        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelName);
        MetaModel metaModel = this.getOne(metaModelLambdaQueryWrapper, false);

        if (ObjectUtil.isEmpty(metaModel)) {
            return "";
        } else {
            return metaModel.getMetaModelName();
        }

    }

    @Override
    public Long getModelIdByModelCode(String modelCode) {
        LambdaQueryWrapper<MetaModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MetaModel::getMetaModelCode, modelCode);
        wrapper.select(MetaModel::getMetaModelId);
        MetaModel metaModel = this.getOne(wrapper, false);
        if (metaModel == null) {
            return null;
        } else {
            return metaModel.getMetaModelId();
        }
    }

    @Override
    public List<MetaModelDTO> getModelFieldInfoList(List<Long> modelIdList) {

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.in(MetaModel::getMetaModelId, modelIdList);
        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelName, MetaModel::getSystemCodeShow,
                MetaModel::getMetaModelCode, MetaModel::getCurrentVersion, MetaModel::getCurrentDefinitionId,
                MetaModel::getMainFlag, MetaModel::getSubTableFieldCode, MetaModel::getSubTableType);
        List<MetaModel> metaModelList = this.list(metaModelLambdaQueryWrapper);
        if (ObjectUtil.isEmpty(metaModelList)) {
            return new ArrayList<>();
        }

        List<Long> definitionIdList = metaModelList.stream().map(MetaModel::getCurrentDefinitionId).collect(Collectors.toList());

        List<MetaField> metaFieldList = metaFieldService.quickGetFieldList(YesOrNotEnum.Y.getCode(), definitionIdList);

        List<MetaModelDTO> result = new ArrayList<>();
        for (MetaModel metaModel : metaModelList) {
            MetaModelDTO metaModelDTO = new MetaModelDTO();
            metaModelDTO.setMetaModelName(metaModel.getMetaModelName());
            metaModelDTO.setSystemCodeShow(metaModel.getSystemCodeShow());
            metaModelDTO.setMetaModelCode(metaModel.getMetaModelCode());
            metaModelDTO.setCurrentVersion(metaModel.getCurrentVersion());

            metaModelDTO.setMainFlag(metaModel.getMainFlag());
            metaModelDTO.setSubTableFieldCode(metaModel.getSubTableFieldCode());
            metaModelDTO.setSubTableType(metaModel.getSubTableType());
            metaModelDTO.setOriginMetaModelCode(metaModel.getMetaModelCode());

            Long currentDefinitionId = metaModel.getCurrentDefinitionId();
            List<MetaField> tempField = metaFieldList.stream().filter(i -> i.getMetaDefinitionId().equals(currentDefinitionId)).collect(Collectors.toList());
            List<MetaFieldDTO> metaFieldDTOS = BeanUtil.copyToList(tempField, MetaFieldDTO.class, CopyOptions.create().ignoreError());
            metaModelDTO.setMetaFieldList(metaFieldDTOS);

            result.add(metaModelDTO);
        }

        return result;
    }

    @Override
    public List<MetaModel> getBusinessMetaModelList(Long businessId, Set<String> tableNameList) {

        if (ObjectUtil.isEmpty(businessId)) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.eq(MetaModel::getBusinessId, businessId);
        if (ObjectUtil.isNotEmpty(tableNameList)) {
            metaModelLambdaQueryWrapper.in(MetaModel::getMetaModelCode, tableNameList);
        }
        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelId, MetaModel::getMetaModelCode, MetaModel::getMetaModelName, MetaModel::getMainFlag, MetaModel::getSubTableFieldCode,
                MetaModel::getSubTableType, MetaModel::getCurrentDefinitionId, MetaModel::getMetaModelType, MetaModel::getLinkModelId);

        return this.list(metaModelLambdaQueryWrapper);
    }

    @Override
    public MetaModel getMainMetaModel(Long businessId) {

        if (ObjectUtil.isEmpty(businessId)) {
            return null;
        }

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.eq(MetaModel::getBusinessId, businessId);
        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelCode, MetaModel::getMainFlag, MetaModel::getSubTableFieldCode, MetaModel::getSubTableType, MetaModel::getCurrentDefinitionId,
                MetaModel::getMetaModelType, MetaModel::getLinkModelId);
        metaModelLambdaQueryWrapper.eq(MetaModel::getMainFlag, YesOrNotEnum.Y.getCode());
        return this.getOne(metaModelLambdaQueryWrapper);
    }

    @Override
    public String getSubTableLinkFieldCode(Long businessId, String tableName) {

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.eq(MetaModel::getBusinessId, businessId);
        metaModelLambdaQueryWrapper.eq(MetaModel::getMetaModelCode, tableName);
        metaModelLambdaQueryWrapper.select(MetaModel::getSubTableFieldCode);
        MetaModel one = this.getOne(metaModelLambdaQueryWrapper, false);

        if (one == null) {
            throw new ServiceException(MetaModelExceptionEnum.CANT_FIND_SUB_TABLE_LINK_FIELD);
        }

        return one.getSubTableFieldCode();
    }

    @Override
    public String getModelDefinitionTableName(Long modelDefinitionId) {
        try {
            MetaModel metaModelNameAndCode = this.getMetaModelNameAndCode(modelDefinitionId);
            return metaModelNameAndCode.getMetaModelCode();
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public MetaModel getMetaModelNameAndCode(Long modelDefinitionId) {

        Long modelId = metaDefinitionService.getMetaModelIdByDefinitionId(modelDefinitionId);
        if (modelId == null) {
            throw new ServiceException(MetaDefinitionExceptionEnum.META_DEFINITION_NOT_EXISTED);
        }

        LambdaQueryWrapper<MetaModel> modelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        modelLambdaQueryWrapper.eq(MetaModel::getMetaModelId, modelId);
        modelLambdaQueryWrapper.select(MetaModel::getMetaModelId, MetaModel::getMetaModelCode, MetaModel::getMetaModelName);
        MetaModel model = this.getOne(modelLambdaQueryWrapper, false);
        if (model == null) {
            throw new ServiceException(MetaModelExceptionEnum.META_MODEL_NOT_EXISTED);
        }

        return model;
    }

    @Override
    public boolean getTableCreateFlag(String metaModelCode) {

        DatabaseMetadataRequest databaseMetadataRequest = DatabaseConnectionContext.currentDatabaseInfo();
        List<TableDescription> tableNameList = databaseMetadataApi.getTableNameList(databaseMetadataRequest);

        return tableNameList.stream().anyMatch(i -> i.getTableCode().equals(metaModelCode));
    }

    @Override
    public Map<Long, Integer> statModelNumber(Set<Long> businessIdList) {
        HashMap<Long, Integer> resultMap = new HashMap<>();

        if (ObjectUtil.isEmpty(businessIdList)) {
            return resultMap;
        }

        LambdaQueryWrapper<MetaModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(MetaModel::getBusinessId, businessIdList);
        wrapper.select(MetaModel::getBusinessId, MetaModel::getMetaModelId);
        List<MetaModel> metaModelList = this.list(wrapper);
        if (ObjectUtil.isEmpty(metaModelList)) {
            return resultMap;
        }

        return metaModelList.stream().collect(Collectors.groupingBy(MetaModel::getBusinessId, Collectors.summingInt(i -> 1)));
    }

    @Override
    public String getMetaModelCode(Long metaModelId) {
        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        metaModelLambdaQueryWrapper.eq(MetaModel::getMetaModelId, metaModelId);
        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelName, MetaModel::getMetaModelCode);
        MetaModel metaModel = this.getOne(metaModelLambdaQueryWrapper, false);
        if (metaModel == null) {
            return null;
        }
        return metaModel.getMetaModelCode();
    }

    @Override
    public void cleanBusinessModel(Long businessId) {

        LambdaQueryWrapper<MetaModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MetaModel::getBusinessId, businessId);
        this.remove(wrapper);

        this.metaDefinitionService.cleanBusinessDefinitions(businessId);

        this.metaFieldService.cleanBusinessFields(businessId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePackageModel(List<MetaModel> metaModelList, List<MetaDefinition> metaDefinitionList, List<MetaField> metaFieldList) {
        this.saveBatch(metaModelList);

        this.metaDefinitionService.saveBatch(metaDefinitionList);

        this.metaFieldService.saveBatch(metaFieldList);
    }

    @Override
    public void executeCreateTable(MetaModel metaModel, List<MetaField> modelFieldList) {

        boolean alreadyCreate = this.getTableCreateFlag(metaModel.getMetaModelCode());
        if (alreadyCreate) {
            return;
        }

        List<CommonGenerateResult> commonGenerateResults = this.commonDoGenerateSql(metaModel, modelFieldList);


        CommonGenerateResult mysql = commonGenerateResults.stream().filter(i -> i.getFileName().equalsIgnoreCase("mysql")).findFirst().get();
        DatabaseConnectionContext.executeUpdateSql(mysql.getFileContent());
    }

    @Override
    public List<MetaModel> getTotalTableList(MetaModelRequest metaModelRequest) {
        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = this.createWrapper(metaModelRequest);
        metaModelLambdaQueryWrapper.select(MetaModel::getCurrentDefinitionId, MetaModel::getMetaModelId, MetaModel::getMetaModelName, MetaModel::getMetaModelCode);

        metaModelLambdaQueryWrapper.eq(MetaModel::getMetaModelType, MetaModelTypeEnum.NEW_MODEL.getCode());
        return this.list(metaModelLambdaQueryWrapper);
    }

    @Override
    public MetaModel getBusinessMainModel(Long businessId) {

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = new LambdaQueryWrapper<>();

        metaModelLambdaQueryWrapper.eq(MetaModel::getBusinessId, businessId);
        metaModelLambdaQueryWrapper.orderByAsc(MetaModel::getFldSort);

        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelId, MetaModel::getCurrentDefinitionId);

        List<MetaModel> list = this.list(metaModelLambdaQueryWrapper);
        if (ObjectUtil.isNotEmpty(list)) {
            return list.get(0);
        } else {
            return null;
        }
    }

    @Override
    public List<MetaModel> getTotalModelAndFieldList(MetaModelRequest metaModelRequest) {

        LambdaQueryWrapper<MetaModel> metaModelLambdaQueryWrapper = this.createWrapper(metaModelRequest);

        metaModelLambdaQueryWrapper.select(MetaModel::getMetaModelId, MetaModel::getMetaModelCode, MetaModel::getCurrentDefinitionId, MetaModel::getMetaModelName, MetaModel::getMetaModelType, MetaModel::getLinkModelId);

        List<MetaModel> list = this.list(metaModelLambdaQueryWrapper);
        if (ObjectUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<Long> metaDefinitionIdList = list.stream().map(MetaModel::getCurrentDefinitionId).collect(Collectors.toList());

        List<MetaField> batchMetaFieldList = metaFieldService.getBatchMetaFieldList(metaDefinitionIdList);

        for (MetaModel metaModel : list) {
            Long currentDefinitionId = metaModel.getCurrentDefinitionId();
            List<MetaField> tempFieldList = batchMetaFieldList.stream().filter(i -> i.getMetaDefinitionId().equals(currentDefinitionId)).collect(Collectors.toList());
            metaModel.setMetaFieldList(tempFieldList);
        }

        return list;
    }

    @Override
    public void createTableIntoDb(Long definitionId) {

        MetaModel metaModel = this.getMetaModelNameAndCode(definitionId);

        String metaModelCode = metaModel.getMetaModelCode();

        boolean alreadyCreate = this.getTableCreateFlag(metaModelCode);
        if (alreadyCreate) {
            throw new ServiceException(MetaModelExceptionEnum.TABLE_EXISTED);
        }

        List<CommonGenerateResult> commonGenerateResults = this.generateCreateTable(metaModel, definitionId);

        CommonGenerateResult mysql = commonGenerateResults.stream().filter(i -> i.getFileName().equalsIgnoreCase("mysql")).findFirst().get();

        DatabaseConnectionContext.executeUpdateSql(mysql.getFileContent());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTableIntoDb(TableUpdateOperateRequest tableUpdateOperateRequest) {

        MetaModel metaModel = this.getMetaModelNameAndCode(tableUpdateOperateRequest.getDefinitionId());
        String tableName = metaModel.getMetaModelCode();

        boolean alreadyCreate = this.getTableCreateFlag(tableName);
        if (!alreadyCreate) {
            throw new ServiceException(MetaModelExceptionEnum.CANT_FIND_TABLE);
        }

        List<TableAlterLog> tableAlterLogList = tableUpdateOperateRequest.getTableAlterLogList();

        this.metaFieldService.updateMetaField(metaModel.getMetaModelId(), tableAlterLogList);

        String sql = this.generateAlterSql(metaModel, tableUpdateOperateRequest);

        DatabaseConnectionContext.executeUpdateSql(sql);
    }

    @Override
    public List<CategoryInfo> getCategoryModelList(MetaModelRequest metaModelRequest) {

        List<CategoryInfo> finalResult = new ArrayList<>();

        List<BusinessCategory> categoryList = businessCategoryApi.getCategoryList(null);
        if (ObjectUtil.isEmpty(categoryList)) {
            return finalResult;
        }

        finalResult = BeanUtil.copyToList(categoryList, CategoryInfo.class);

        List<MetaModel> metaModelList = this.findList(metaModelRequest);
        Map<Long, List<MetaModel>> categoryGroup = metaModelList.stream().collect(Collectors.groupingBy(MetaModel::getBusinessCategoryId));

        for (CategoryInfo metaModelCategory : finalResult) {
            Long modelCategoryId = metaModelCategory.getBusinessCategoryId();
            List<MetaModel> tempList = categoryGroup.get(modelCategoryId);
            metaModelCategory.setMetaModelList(tempList);
        }

        return finalResult;
    }

    @Override
    public String generateAlterSql(MetaModel metaModel, TableUpdateOperateRequest tableUpdateOperateRequest) {

        List<TableAlterLog> tableAlterLogList = tableUpdateOperateRequest.getTableAlterLogList();
        if (ObjectUtil.isEmpty(tableAlterLogList)) {
            return "获取不到更新字段的信息！无法生成Alter语句";
        }

        List<GenerationTableAlter> generationTableAlterList = metaFieldService.getGenerationTableAlterList(tableAlterLogList);

        GeneratorTemplateGroup templateGroup = templateGetApi.getTemplateGroup(GeneratorTypeEnum.ALTER_TABLE);
        Dict dict = Dict.create();
        dict.set("metaModelCode", metaModel.getMetaModelCode());
        dict.set("alterInfoList", generationTableAlterList);
        CommonGenerateResult commonGenerateResult = codeGeneratorApi.generateCodeGetResult(templateGroup.getGeneratorTemplates().get(0), "", dict);

        return commonGenerateResult.getFileContent();

    }

    @Override
    public Boolean validateTableExisted(String tableName) {

        DatabaseMetadataRequest databaseMetadataRequest = DatabaseConnectionContext.currentDatabaseInfo();
        List<TableDescription> tableNameList = databaseMetadataApi.getTableNameList(databaseMetadataRequest);

        for (TableDescription tableDescription : tableNameList) {
            if (tableName.equalsIgnoreCase(tableDescription.getTableCode())) {
                return true;
            }
        }

        return false;
    }

    private MetaModel validateCodeRepeat(MetaModelRequest metaModelRequest) {

        LambdaQueryWrapper<MetaModel> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(MetaModel::getMetaModelCode, metaModelRequest.getMetaModelCode());
        wrapper2.select(MetaModel::getMetaModelId);
        return this.getOne(wrapper2, false);
    }

    @Override
    public List<CommonGenerateResult> generateCreateTable(Long metaModelId) {

        List<MetaModelCreatSqlDTO> metaModelFieldInfoList = createTableGenerateService.getMetaModelFieldInfoList(
                ListUtil.list(false, metaModelId), null);

        GeneratorTemplateGroup templateGroup = templateGetApi.getTemplateGroup(GeneratorTypeEnum.CREAT_SQL);
        return createTableGenerateService.codeGenerate(templateGroup, metaModelFieldInfoList);
    }

    @Override
    public List<CommonGenerateResult> generateCreateTable(MetaModel metaModel, Long definitionId) {

        List<MetaField> metaFieldList = metaFieldService.quickGetFieldList(YesOrNotEnum.Y.getCode(), ListUtil.of(definitionId));
        if (ObjectUtil.isEmpty(metaFieldList)) {
            throw new ServiceException(MetaModelExceptionEnum.FIELD_IS_EMPTY);
        }

        return commonDoGenerateSql(metaModel, metaFieldList);
    }

    private MetaModel queryMetaModel(MetaModelRequest metaModelRequest) {
        MetaModel metaModel = this.getById(metaModelRequest.getMetaModelId());
        if (ObjectUtil.isEmpty(metaModel)) {
            throw new ServiceException(MetaModelExceptionEnum.META_MODEL_NOT_EXISTED);
        }
        return metaModel;
    }

    private LambdaQueryWrapper<MetaModel> createWrapper(MetaModelRequest metaModelRequest) {
        LambdaQueryWrapper<MetaModel> queryWrapper = new LambdaQueryWrapper<>();

        String searchText = metaModelRequest.getSearchText();
        if (StrUtil.isNotBlank(searchText)) {
            queryWrapper.nested(i -> i.like(MetaModel::getMetaModelName, searchText)
                    .or().like(MetaModel::getMetaModelCode, searchText)
                    .or().like(MetaModel::getSystemCodeShow, searchText));
        }

        Long businessId = metaModelRequest.getBusinessId();
        if (ObjectUtil.isNotEmpty(businessId)) {
            queryWrapper.eq(MetaModel::getBusinessId, businessId);
        }

        queryWrapper.orderByAsc(MetaModel::getFldSort, MetaModel::getMetaModelId);

        return queryWrapper;
    }

    private void validateRepeat(MetaModelRequest metaModelRequest, boolean editFlag) {

        if (MetaModelTypeEnum.NEW_MODEL.getCode().equals(metaModelRequest.getMetaModelType())) {
            LambdaQueryWrapper<MetaModel> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(MetaModel::getMetaModelName, metaModelRequest.getMetaModelName());
            if (editFlag) {
                wrapper1.ne(MetaModel::getMetaModelId, metaModelRequest.getMetaModelId());
            }
            long nameNumber = this.count(wrapper1);
            if (nameNumber > 0) {
                throw new ServiceException(MetaModelExceptionEnum.NAME_REPEAT);
            }
        }

        if (MetaModelTypeEnum.NEW_MODEL.getCode().equals(metaModelRequest.getMetaModelType())) {
            LambdaQueryWrapper<MetaModel> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.eq(MetaModel::getMetaModelCode, metaModelRequest.getMetaModelCode());
            if (editFlag) {
                wrapper2.ne(MetaModel::getMetaModelId, metaModelRequest.getMetaModelId());
            }
            long codeNumber = this.count(wrapper2);
            if (codeNumber > 0) {
                throw new ServiceException(MetaModelExceptionEnum.CODE_REPEAT);
            }
        }

        LambdaQueryWrapper<MetaModel> wrapper3 = new LambdaQueryWrapper<>();
        wrapper3.eq(MetaModel::getSystemCode, metaModelRequest.getSystemCode());
        if (editFlag) {
            wrapper3.ne(MetaModel::getMetaModelId, metaModelRequest.getMetaModelId());
        }
        long systemCodeNumber = this.count(wrapper3);

        if (systemCodeNumber > 0) {
            throw new ServiceException(ProjectExceptionEnum.DEVOPS_SYSTEM_CODE_ERROR);
        }
    }

    private List<CommonGenerateResult> commonDoGenerateSql(MetaModel metaModel, List<MetaField> metaFieldList) {
        MetaModelCreatSqlDTO metaModelCreatSqlDTO = new MetaModelCreatSqlDTO();
        metaModelCreatSqlDTO.setMetaFieldList(metaFieldList);
        metaModelCreatSqlDTO.setMetaModelName(metaModel.getMetaModelName());
        metaModelCreatSqlDTO.setMetaModelCode(metaModel.getMetaModelCode());

        List<MetaModelCreatSqlDTO> modelFieldInfoList = new ArrayList<>();
        modelFieldInfoList.add(metaModelCreatSqlDTO);

        GeneratorTemplateGroup templateGroup = templateGetApi.getTemplateGroup(GeneratorTypeEnum.CREAT_SQL);
        return createTableGenerateService.codeGenerate(templateGroup, modelFieldInfoList);
    }

}