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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
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.pojo.generator.result.CommonGenerateResult;
import cn.stylefeng.team.generator.api.pojo.template.GeneratorTemplate;
import cn.stylefeng.team.generator.api.pojo.template.GeneratorTemplateGroup;
import cn.stylefeng.team.meta.api.constants.MetaConstants;
import cn.stylefeng.team.meta.api.entity.MetaField;
import cn.stylefeng.team.meta.api.entity.MetaModel;
import cn.stylefeng.team.meta.api.pojo.MetaModelCreatSqlDTO;
import cn.stylefeng.team.meta.modular.enums.MetaModelExceptionEnum;
import cn.stylefeng.team.meta.modular.factory.CreateTableMetaFactory;
import cn.stylefeng.team.meta.modular.pojo.GenerationSql;
import cn.stylefeng.team.meta.modular.pojo.request.MetaModelRequest;
import cn.stylefeng.team.meta.modular.service.CreateTableGenerateService;
import cn.stylefeng.team.meta.modular.service.MetaFieldService;
import cn.stylefeng.team.meta.modular.service.MetaModelService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class CreateTableGenerateImpl implements CreateTableGenerateService {

    @Resource
    private CodeGeneratorApi codeGeneratorApi;

    @Resource
    private MetaModelService metaModelService;

    @Resource
    private MetaFieldService metaFieldService;

    @Override
    public List<MetaModelCreatSqlDTO> getBusinessMetaModelFieldInfoList(MetaModelRequest metaModelRequest) {

        List<MetaModel> metaModelList = metaModelService.findList(metaModelRequest);

        return this.getMetaModelFieldInfoList(null, metaModelList);
    }

    @Override
    public List<MetaModelCreatSqlDTO> getMetaModelFieldInfoList(List<Long> metaModelIdList, List<MetaModel> metaModelList) {

        List<MetaModel> paramMetaModelList = null;
        if (ObjectUtil.isNotEmpty(metaModelList)) {
            paramMetaModelList = metaModelList;
        } else {
            if (ObjectUtil.isEmpty(metaModelIdList)) {
                return Collections.emptyList();
            }
            LambdaQueryWrapper<MetaModel> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(MetaModel::getMetaModelId, metaModelIdList);
            paramMetaModelList = metaModelService.list(queryWrapper);
        }

        List<Long> modelDefinitionIdList = new ArrayList<>();
        for (MetaModel metaModel : paramMetaModelList) {
            Long currentDefinitionId = metaModel.getCurrentDefinitionId();
            modelDefinitionIdList.add(currentDefinitionId);
        }

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

        List<MetaModelCreatSqlDTO> metaModelCreatSqlDTOList = new ArrayList<>();
        for (MetaModel metaModel : paramMetaModelList) {
            MetaModelCreatSqlDTO metaModelCreatSqlDTO = new MetaModelCreatSqlDTO();
            metaModelCreatSqlDTO.setMetaModelName(metaModel.getMetaModelName());
            metaModelCreatSqlDTO.setMetaModelCode(metaModel.getMetaModelCode());
            metaModelCreatSqlDTO.setMetaFieldList(new ArrayList<>());
            for (MetaField metaField : metaFieldList) {
                if (metaField.getMetaDefinitionId().equals(metaModel.getCurrentDefinitionId())) {
                    metaModelCreatSqlDTO.getMetaFieldList().add(metaField);
                }
            }
            metaModelCreatSqlDTOList.add(metaModelCreatSqlDTO);
        }

        return metaModelCreatSqlDTOList;
    }

    @Override
    public List<CommonGenerateResult> codeGenerate(GeneratorTemplateGroup templateGroup, List<MetaModelCreatSqlDTO> modelFieldInfoList) {

        List<CommonGenerateResult> commonGenerateResultList = new ArrayList<>();

        for (MetaModelCreatSqlDTO metaModelCreatSqlDTO : modelFieldInfoList) {

            Dict generationTotalMetadata = this.packageMetadata(metaModelCreatSqlDTO);

            for (GeneratorTemplate generatorTemplate : templateGroup.getGeneratorTemplates()) {

                CommonGenerateResult commonGenerateResult = codeGeneratorApi.generateCodeGetResult(generatorTemplate, "",
                        generationTotalMetadata);

                if (generatorTemplate.getFileSuffix().endsWith("mysql")) {
                    commonGenerateResult.setFileName(MetaConstants.MYSQL_CREATE_TABLE_FILE_NAME);
                } else if (generatorTemplate.getFileSuffix().endsWith("oracle")) {
                    commonGenerateResult.setFileName(MetaConstants.ORACLE_CREATE_TABLE_FILE_NAME);
                } else if (generatorTemplate.getFileSuffix().endsWith("pgsql")) {
                    commonGenerateResult.setFileName(MetaConstants.POSTGRESQL_CREATE_TABLE_FILE_NAME);
                }

                commonGenerateResult.setFilePath(null);

                commonGenerateResultList.add(commonGenerateResult);
            }
        }

        return commonGenerateResultList;
    }

    private Dict packageMetadata(MetaModelCreatSqlDTO metaModelCreatSqlDTO) {

        Dict finalResultMetadata = Dict.create();

        GenerationSql generationModel = CreateTableMetaFactory.generationSql(metaModelCreatSqlDTO);

        finalResultMetadata.putAll(BeanUtil.beanToMap(generationModel));

        return finalResultMetadata;
    }

}
