package cn.stylefeng.team.meta.modular.factory;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.team.meta.api.entity.MetaField;
import cn.stylefeng.team.meta.api.pojo.db.DatabaseFieldDTO;
import cn.stylefeng.team.meta.api.pojo.db.DatabaseTableDTO;
import cn.stylefeng.team.meta.sdk.parser.MysqlTypeToMetaFieldType;
import cn.stylefeng.team.meta.sdk.util.TableSchemaCreateUtil;
import lombok.extern.slf4j.Slf4j;

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

@Slf4j
public class CalcFieldFactory {

    public static String compareAndCalcField(List<MetaField> metaFieldList, DatabaseTableDTO dbTableFieldList) {

        List<String> metaFieldCodeList = metaFieldList.stream().map(MetaField::getFieldCode).collect(Collectors.toCollection(LinkedList::new));

        List<String> dbFieldCodeList = dbTableFieldList.getGenDatabaseFieldDtoList().stream().map(DatabaseFieldDTO::getFieldCode).collect(Collectors.toCollection(LinkedList::new));

        List<String> deleteFieldList = dbFieldCodeList.stream().filter(i -> !metaFieldCodeList.contains(i)).collect(Collectors.toCollection(LinkedList::new));

        List<MetaField> addFieldList = metaFieldList.stream().filter(i -> !dbFieldCodeList.contains(i.getFieldCode())).collect(Collectors.toCollection(LinkedList::new));

        List<MetaField> commonHaveFieldList = metaFieldList.stream().filter(i -> dbFieldCodeList.contains(i.getFieldCode())).collect(Collectors.toCollection(LinkedList::new));

        List<MetaField> needModifyFieldList = new LinkedList<>();
        for (MetaField metaField : commonHaveFieldList) {
            for (DatabaseFieldDTO databaseFieldDTO : dbTableFieldList.getGenDatabaseFieldDtoList()) {
                if (metaField.getFieldCode().equals(databaseFieldDTO.getFieldCode())) {

                    String dbFieldType = MysqlTypeToMetaFieldType.getSqlType(metaField.getFieldType());
                    if (dbFieldType != null && !dbFieldType.equalsIgnoreCase(databaseFieldDTO.getFieldType())) {
                        needModifyFieldList.add(metaField);
                    }

                    else if (ObjectUtil.isNotEmpty(metaField.getFieldLength()) && !metaField.getFieldLength().equals(databaseFieldDTO.getFieldLength())) {

                        if (MysqlTypeToMetaFieldType.VARCHAR.getMysqlType().equalsIgnoreCase(dbFieldType) || MysqlTypeToMetaFieldType.DECIMAL.getMysqlType()
                                .equalsIgnoreCase(dbFieldType) || MysqlTypeToMetaFieldType.ONE_CHAR.getMysqlType().equalsIgnoreCase(dbFieldType)) {
                            needModifyFieldList.add(metaField);
                        }
                    }
                }
            }
        }

        String alterSql = createAlterSql(dbTableFieldList.getTableName(), deleteFieldList, addFieldList, needModifyFieldList);
        log.info("生成的alter语句为：{}", alterSql);
        return alterSql;
    }

    public static String createAlterSql(String tableName, List<String> deleteFieldList, List<MetaField> addFieldList, List<MetaField> needModifyFieldList) {

        if (ObjectUtil.isAllEmpty(deleteFieldList, addFieldList, needModifyFieldList)) {
            return null;
        }

        StringBuilder alterSql = new StringBuilder();

        alterSql.append("alter table `").append(tableName).append("` \n");

        if (ObjectUtil.isNotEmpty(deleteFieldList)) {
            for (String deleteField : deleteFieldList) {
                alterSql.append("drop column `").append(deleteField).append("`,\n");
            }
        }

        if (ObjectUtil.isNotEmpty(addFieldList)) {
            for (MetaField metaField : addFieldList) {
                alterSql.append("add column ").append(TableSchemaCreateUtil.fieldTypeMetaCreate(metaField)).append(",\n");
            }
        }

        if (ObjectUtil.isNotEmpty(needModifyFieldList)) {
            for (MetaField metaField : needModifyFieldList) {
                alterSql.append("modify column ").append(TableSchemaCreateUtil.fieldTypeMetaCreate(metaField)).append(",\n");
            }
        }

        return StrUtil.removeSuffix(alterSql.toString(), ",\n") + ";";
    }

}
