package com.seezoon.generator.plan.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.seezoon.generator.constants.InputType;
import com.seezoon.generator.constants.QueryType;
import com.seezoon.generator.constants.TemplateType;
import com.seezoon.generator.constants.db.ColumnDataType;
import com.seezoon.generator.constants.db.ColumnExtra;
import com.seezoon.generator.constants.db.ColumnKey;
import com.seezoon.generator.constants.db.DefaultColumns;
import com.seezoon.generator.dto.db.DbTable;
import com.seezoon.generator.dto.db.DbTableColumn;
import com.seezoon.generator.plan.ColumnPlan;
import com.seezoon.generator.plan.PkPlan;
import com.seezoon.generator.plan.TablePlan;
import com.seezoon.generator.plan.TablePlanHandler;

/**
 * 系统默认生成方案
 *
 * @author hdf
 */
public class SystemTablePlanHandlerImpl implements TablePlanHandler {

    private static final Logger logger = LoggerFactory.getLogger(SystemTablePlanHandlerImpl.class);
    /**
     * DB 及表字段的分隔符
     */
    private static final String DB_DELIMITER = "_";

    @Override
    public TablePlan generate(DbTable dbTable, List<DbTableColumn> dbTableColumns) {
        TablePlan tablePlan = new TablePlan();
        tablePlan.setTableName(dbTable.getName());
        tablePlan.setMenuName(dbTable.getComment());
        // 放入默认的模块名和功能名
        List<String> moduleAndFuntion = extractModuleAndFuntion(dbTable.getName());
        tablePlan.setModuleName(moduleAndFuntion.get(0));
        tablePlan.setFunctionName(moduleAndFuntion.get(1));
        tablePlan.setTemplateType(TemplateType.CRUD.ordinal());
        tablePlan.setClassName(CaseUtils.toCamelCase(dbTable.getName(), true, DB_DELIMITER.toCharArray()));
        tablePlan.setColumnPlans(this.createColumnPlan(tablePlan, dbTableColumns));
        return tablePlan;
    }

    private List<ColumnPlan> createColumnPlan(TablePlan tablePlan, List<DbTableColumn> dbTableColumns) {
        List<ColumnPlan> columnPlans = new ArrayList<>();
        dbTableColumns.forEach((v) -> {
            // @formatter:off
            ColumnPlan columnPlan = ColumnPlan.builder()
                    .dbColumnName(v.getName())
                    .fieldName(v.getComment())
                    .columnKey(StringUtils.isNotEmpty(v.getColumnKey()) ? ColumnKey.valueOf(v.getColumnKey())
                            : ColumnKey.NONE)
                    .extra(StringUtils.isNotEmpty(v.getExtra()) ? ColumnExtra.valueOf(v.getExtra()) : ColumnExtra.none)
                    .columnType(v.getColumnType())
                    .dataType(ColumnDataType.parse(v.getDataType()))
                    .maxLength(v.getMaxlength())
                    .javaFieldName(CaseUtils.toCamelCase(v.getName(), false, DB_DELIMITER.toCharArray()))
                    .nullable(v.getNullable())
                    .sort(v.getSort())
                    .queryType(QueryType.NONE)
                    .sortable(false)
                    .insert(true)
                    .update(true)
                    .list(true)
                    .inputType(InputType.NONE)
                    .build();
            // @formatter:on
            columnPlan.setInsert(true);
            columnPlan.setUpdate(true);
            columnPlan.setList(true);

            // 针对默认字段的处理
            if (columnPlan.isDefaultField()) {
                if (DefaultColumns.id.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setInputType(InputType.HIDDEN);
                    columnPlan.setList(false);
                    columnPlan.setInsert(false);
                    columnPlan.setUpdate(false);
                } else if (DefaultColumns.status.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setInputType(InputType.RADIO);
                } else if (DefaultColumns.create_time.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setSortable(true);
                    columnPlan.setUpdate(false);
                    columnPlan.setInputType(InputType.DATETIME);
                } else if (DefaultColumns.update_time.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setList(false);
                    columnPlan.setInputType(InputType.DATETIME);
                } else if (DefaultColumns.create_by.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setInputType(InputType.INTEGRAL_NUMBER);
                    columnPlan.setList(false);
                    columnPlan.setUpdate(false);
                } else if (DefaultColumns.update_by.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setInputType(InputType.INTEGRAL_NUMBER);
                    columnPlan.setList(false);
                } else if (DefaultColumns.remarks.name().equals(columnPlan.getDbColumnName())) {
                    columnPlan.setInputType(InputType.TEXTAREA);
                    columnPlan.setList(false);
                }
            } else {
                // 默认文本框
                if (columnPlan.isStringType()) {
                    columnPlan.setInputType(InputType.TEXT);
                }
                // 时间框
                if (Date.class.getSimpleName().equals(columnPlan.getDataType().javaType())) {
                    if (ColumnDataType.DATE.dbType().equals(columnPlan.getDataType().dbType())) {
                        columnPlan.setInputType(InputType.DATE);
                    } else {
                        columnPlan.setInputType(InputType.DATETIME);
                    }
                }

                // jdbcType = LONGVARCHAR的为大文本
                if (columnPlan.isBlobType()) {
                    columnPlan.setInputType(InputType.TEXTAREA);
                    // 列表默认也不展示
                    columnPlan.setList(false);
                }

                // 数值
                if (ArrayUtils.contains(new String[] {Integer.class.getSimpleName(), Long.class.getSimpleName(),
                    Short.class.getSimpleName()}, columnPlan.getDataType().javaType())) {
                    columnPlan.setInputType(InputType.INTEGRAL_NUMBER);
                } else if (ArrayUtils.contains(new String[] {Float.class.getSimpleName(), Double.class.getSimpleName()},
                    columnPlan.getDataType().javaType())) {
                    columnPlan.setInputType(InputType.DECIMAL);
                } else if (BigDecimal.class.getSimpleName().equals(columnPlan.getDataType().javaType())) {
                    columnPlan.setInputType(InputType.DECIMAL);
                }

                // 有索引的
                if ((ColumnKey.MUL.equals(columnPlan.getColumnKey())
                    || ColumnKey.UNI.equals(columnPlan.getColumnKey()))) {
                    columnPlan.setSearch(true);
                    columnPlan.setSortable(true);
                    columnPlan.setQueryType(QueryType.EQUAL);
                }
            }

            // 主键
            if (columnPlan.getColumnKey().equals(ColumnKey.PRI)) {
                if (null != tablePlan.getPkPlan()) {
                    logger.warn("table[{}] must have only one primary key,otherwise generator select first primary key",
                        tablePlan.getTableName());
                } else {
                    columnPlan.setInputType(InputType.HIDDEN);
                    columnPlan.setList(false);
                    tablePlan.setPkPlan(new PkPlan(columnPlan.getDbColumnName(), columnPlan.getJavaFieldName(),
                        columnPlan.getDataType(), DefaultColumns.id.name().equals(columnPlan.getJavaFieldName()),
                        ColumnExtra.auto_increment.equals(columnPlan.getExtra())));
                    // 自增不可插入
                    columnPlan.setInsert(!tablePlan.getPkPlan().isAutoIncrement());
                    // 主键也不可更新
                    columnPlan.setUpdate(false);
                }
            }
            columnPlans.add(columnPlan);
        });
        // 一定要有主键
        if (null == tablePlan.getPkPlan()) {
            throw new IllegalArgumentException(
                String.format("table[%s] must have primary key", tablePlan.getTableName()));
        }
        return columnPlans;
    }

    /**
     * 通过表名提取模块名和功能名，按{@link SystemTablePlanHandlerImpl#DB_DELIMITER} 拆分为2个，只拆第一个分隔符
     *
     * @param tableName
     *            not null
     * @return
     */
    private List<String> extractModuleAndFuntion(String tableName) {
        String[] splitedTableName = tableName.split(DB_DELIMITER, 2);
        return List.of(splitedTableName[0], splitedTableName.length == 2 ? splitedTableName[1] : splitedTableName[0]);
    }
}
