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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.team.meta.api.entity.MetaDefinition;
import cn.stylefeng.team.meta.api.entity.MetaField;
import cn.stylefeng.team.meta.api.enums.TableAlterTypeEnum;
import cn.stylefeng.team.meta.api.pojo.table.TableAlterLog;

import java.util.List;

public class AlterFieldFactory {

    public static List<MetaField> calcAlterResult(MetaDefinition metaDefinition,
                                                  List<MetaField> originFieldList,
                                                  List<TableAlterLog> tableAlterLogList) {

        List<MetaField> alterResult = BeanUtil.copyToList(originFieldList, MetaField.class);

        if (ObjectUtil.isEmpty(tableAlterLogList)) {
            return alterResult;
        }

        for (TableAlterLog tableAlterLog : tableAlterLogList) {

            if (TableAlterTypeEnum.ADD_COLUMN.getCode().equals(tableAlterLog.getOperationType())) {

                MetaField alterMetaField = createAlterMetaField(metaDefinition, tableAlterLog);


                if ("-1".equals(tableAlterLog.getAfterFieldCode()) || tableAlterLog.getAfterFieldCode() == null) {
                    alterResult.add(0, alterMetaField);
                }

                else {
                    int index = findFieldIndexByCode(alterResult, tableAlterLog.getAfterFieldCode());
                    if (index != -1) {
                        alterResult.add(index + 1, alterMetaField);
                    }
                }
            }

            else if (TableAlterTypeEnum.DROP_COLUMN.getCode().equals(tableAlterLog.getOperationType())) {
                alterResult.removeIf(field -> field.getFieldCode().equals(tableAlterLog.getFieldCode()));
            }

            else if (TableAlterTypeEnum.CHANGE_COLUMN.getCode().equals(tableAlterLog.getOperationType())) {
                int index = findFieldIndexByCode(alterResult, tableAlterLog.getOriginFieldCode());
                if (index != -1) {
                    MetaField originField = alterResult.get(index);

                    commonUpdateMetaField(tableAlterLog, originField);
                }

                if (tableAlterLog.getAfterFieldCode() == null) {
                    continue;
                }

                MetaField modifiedField = alterResult.remove(index);

                if ("-1".equals(tableAlterLog.getAfterFieldCode())) {
                    alterResult.add(0, modifiedField);
                }

                else {
                    int afterIndex = findFieldIndexByCode(alterResult, tableAlterLog.getAfterFieldCode());
                    if (afterIndex != -1) {
                        alterResult.add(afterIndex + 1, modifiedField);
                    }
                }
            }
        }

        FieldFactory.simpleSetSortField(alterResult);

        return alterResult;
    }

    public static MetaField createAlterMetaField(MetaDefinition metaDefinition, TableAlterLog tableAlterLog) {
        MetaField metaField = new MetaField();

        metaField.setBusinessCategoryId(metaDefinition.getBusinessCategoryId());
        metaField.setBusinessId(metaDefinition.getBusinessId());
        metaField.setMetaModelId(metaDefinition.getMetaModelId());
        metaField.setMetaDefinitionId(metaDefinition.getMetaDefinitionId());

        commonUpdateMetaField(tableAlterLog, metaField);

        if (metaField.getFieldCode().equals("id")) {
            metaField.setNotEmptyFlag(YesOrNotEnum.Y.getCode());
            metaField.setKeyFlag(YesOrNotEnum.Y.getCode());
        }

        return metaField;
    }

    private static int findFieldIndexByCode(List<MetaField> fields, String fieldCode) {
        for (int i = 0; i < fields.size(); i++) {
            if (fields.get(i).getFieldCode().equals(fieldCode)) {
                return i;
            }
        }
        return -1;
    }

    private static void commonUpdateMetaField(TableAlterLog tableAlterLog, MetaField originField) {
        originField.setFieldCode(tableAlterLog.getFieldCode());
        originField.setFieldType(tableAlterLog.getFieldType());
        originField.setFieldLength(tableAlterLog.getFieldLength());
        originField.setDecimalLength(tableAlterLog.getDecimalLength());
        originField.setNotEmptyFlag(tableAlterLog.getNotEmptyFlag());
        originField.setKeyFlag(tableAlterLog.getKeyFlag());
        originField.setDefaultValue(tableAlterLog.getDefaultValue());
        originField.setRealFlag(tableAlterLog.getRealFlag());
        originField.setDescription(tableAlterLog.getDescription());
    }

}
