package com.cm.common.plugin.service.dynamic.impl;

import com.cm.common.base.AbstractService;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SaveException;
import com.cm.common.exception.SearchException;
import com.cm.common.exception.UpdateException;
import com.cm.common.plugin.dao.dynamic.IDynamicTableDao;
import com.cm.common.plugin.enums.database.table.ColumnDataTypeEnum;
import com.cm.common.plugin.enums.database.table.ColumnIsNullableEnum;
import com.cm.common.plugin.pojo.dtos.database.table.TableColumnDTO;
import com.cm.common.plugin.pojo.dtos.database.table.TableDTO;
import com.cm.common.plugin.pojo.vos.database.table.TableColumnVO;
import com.cm.common.plugin.pojo.vos.database.table.TableVO;
import com.cm.common.plugin.service.dynamic.IDynamicTableService;
import com.cm.common.utils.WStringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: DynamicTableServiceImpl
 * @Description: 动态表格
 * @Author: WangGeng
 * @Date: 2019/12/3 10:55 下午
 * @Version: 1.0
 **/
@Service
public class DynamicTableServiceImpl extends AbstractService implements IDynamicTableService {

    @Autowired
    private IDynamicTableDao dynamicTableDao;

    @Override
    public void createTable(TableVO tableVO) throws SaveException {
        dynamicTableDao.createTable(getSaveTableSQL(tableVO.getTableName(), tableVO.getTableColumns()));
    }

    @Override
    public void saveTableColumn(String tableName, TableColumnVO tableColumnVO) throws UpdateException {
        StringBuilder saveTableColumnSQL = new StringBuilder(String.format("ALTER TABLE `%s%s` ADD COLUMN ", DYNAMIC_TABLE_PREFIX, WStringUtil.lowerUpper2UnderLine(tableName))).append(getSaveColumnSql(tableColumnVO));
        dynamicTableDao.saveTableColumn(saveTableColumnSQL.toString());
    }

    @Override
    public void updateTableColumnType(String tableName, TableColumnVO tableColumnVO) throws UpdateException {
        StringBuilder updateTableColumnTypeSQL = new StringBuilder(String.format("ALTER TABLE `%s%s` MODIFY ", DYNAMIC_TABLE_PREFIX, WStringUtil.lowerUpper2UnderLine(tableName))).append(getSaveColumnSql(tableColumnVO));
        dynamicTableDao.updateTableColumnType(updateTableColumnTypeSQL.toString());
    }

    @Override
    public void deleteTableColumnType(String tableName, String deleteDynamicFormField) throws RemoveException {
        StringBuilder deleteTableColumnTypeSQL = new StringBuilder(String.format("ALTER TABLE `%s%s` DROP `%s`", DYNAMIC_TABLE_PREFIX, WStringUtil.lowerUpper2UnderLine(tableName), deleteDynamicFormField));
        dynamicTableDao.deleteTableColumnType(deleteTableColumnTypeSQL.toString());
    }

    @Override
    public TableDTO getTableByTableName(String tableName) throws SearchException {
        return dynamicTableDao.getTableByTableName(String.format("%s%s", DYNAMIC_TABLE_PREFIX, WStringUtil.lowerUpper2UnderLine(tableName)));
    }

    @Override
    public List<TableColumnDTO> listTableColumns(String tableName) throws SearchException {
        return dynamicTableDao.listTableColumns(String.format("%s%s", DYNAMIC_TABLE_PREFIX, WStringUtil.lowerUpper2UnderLine(tableName)));
    }

    /**
     * 获取建表SQL语句
     *
     * @param tableName
     * @param tableColumns
     * @return
     */
    private String getSaveTableSQL(String tableName, List<TableColumnVO> tableColumns) {
        String underLineTableName = WStringUtil.lowerUpper2UnderLine(tableName);
        StringBuilder sql = new StringBuilder("CREATE TABLE `").append(DYNAMIC_TABLE_PREFIX).append(underLineTableName).append("`(");
        sql.append("`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',");
        sql.append(String.format("`%s_id` CHAR(36) NOT NULL COMMENT '主键',", underLineTableName));
        for (TableColumnVO tableColumn : tableColumns) {
            sql.append(getSaveColumnSql(tableColumn)).append(",");
        }
        sql.append("`creator` CHAR(36) DEFAULT NULL,");
        sql.append("`gmt_create` datetime DEFAULT NULL,");
        sql.append("`modifier` CHAR(36) DEFAULT NULL,");
        sql.append("`gmt_modified` datetime DEFAULT NULL,");
        sql.append("`is_delete` int(1) DEFAULT '0',");
        sql.append(String.format("PRIMARY KEY (`id`, `%s_id`)", underLineTableName));
        sql.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
        return sql.toString();
    }

    /**
     * 新增列的SQL
     *
     * @param tableColumn
     * @return
     */
    private String getSaveColumnSql(TableColumnVO tableColumn) {
        boolean notNull = true;
        StringBuilder columnSql = new StringBuilder();
        if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.VARCHAR.getDataType())) {
            columnSql.append(String.format("`%s` VARCHAR(%d)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.INT.getDataType())) {
            columnSql.append(String.format("`%s` INT(%d)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.DOUBLE.getDataType())) {
            columnSql.append(String.format("`%s` DOUBLE(%d, %d)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength(), tableColumn.getColumnFloatLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.BIGINT.getDataType())) {
            columnSql.append(String.format("`%s` BIGINT(%d)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.CHAR.getDataType())) {
            columnSql.append(String.format("`%s` CHAR(%d)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.DATE.getDataType())) {
            columnSql.append(String.format("`%s` VARCHAR(40)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.DATETIME.getDataType())) {
            columnSql.append(String.format("`%s` VARCHAR(50)", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.TEXT.getDataType())) {
            columnSql.append(String.format("`%s` TEXT DEFAULT NULL", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
            notNull = false;
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.LONGTEXT.getDataType())) {
            columnSql.append(String.format("`%s` LONGTEXT DEFAULT NULL", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
            notNull = false;
        } else if (StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.ID_AND_NAME.getDataType())
                || StringUtils.equals(tableColumn.getDataType(), ColumnDataTypeEnum.IDS_AND_NAMES.getDataType())) {
            columnSql.append(String.format("`%s` VARCHAR(500) DEFAULT NULL", WStringUtil.lowerUpper2UnderLine(tableColumn.getColumnName()), tableColumn.getColumnLength()));
            notNull = false;
        }
        if (notNull && StringUtils.equals(tableColumn.getIsNullable(), ColumnIsNullableEnum.YES.getIsNullable())) {
            columnSql.append(" NOT NULL");
        }
        if (!StringUtils.isEmpty(tableColumn.getColumnDefault())) {
            columnSql.append(String.format(" DEFAULT '%s'", tableColumn.getColumnDefault()));
        }
        if (!StringUtils.isEmpty(tableColumn.getColumnComment())) {
            columnSql.append(String.format(" COMMENT '%s'", tableColumn.getColumnComment()));
        }
        return columnSql.toString();
    }
}
