package org.springblade.datasource.transform.postgresql;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.exception.ServiceException;
import org.springblade.datasource.enums.DsTypeEnum;
import org.springblade.datasource.support.DynamicDataSourceSupport;
import org.springblade.datasource.transform.ColumnEnum;
import org.springblade.datasource.transform.ColumnInfo;
import org.springblade.datasource.transform.ITransform;
import org.springblade.datasource.transform.TableInfo;
import org.springblade.datasource.transform.general.GeneralEnum;
import org.springblade.datasource.transform.general.GeneralModel;
import org.springblade.etl.entity.SqlColumn;
import org.springblade.etl.entity.bi.ReportDatasource;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

/**
 * @author 喜欢番茄火锅
 * @date 2023/9/6 15:43
 */
@Slf4j
@Component
public class PostgreSQLTransform implements ITransform {
    /**
     * 翻译数据库字段
     *
     * @param model
     * @param sqlColumns
     * @return
     */
    @Override
    public List<ColumnInfo> transformColumns(List<GeneralModel> model, List<SqlColumn> sqlColumns) {
        PostgreSQLCreateTableHandle handle = new PostgreSQLCreateTableHandle();
        return model.stream().map(c -> {
            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setColumnComments(c.getColumnComments());
            columnInfo.setColumnName(c.getColumnName());
            columnInfo.setColumnSize(c.getColumnSize());
            columnInfo.setDecimalDigits(c.getDecimalDigits());
            if (c.getSourceColumn()) {
                SqlColumn sqlColumn = sqlColumns.stream().filter(v -> v.getColumnType().equalsIgnoreCase(c.getType())).findAny().orElseThrow(() -> new ServiceException("转换模型源端字段类型错误!"));
                columnInfo.setColumnType(ColumnEnum.valueOf(sqlColumn.getSqlColumnType().toUpperCase(Locale.ROOT)));
            } else {
                columnInfo.setColumnType(GeneralEnum.valueOf(c.getType().toUpperCase()).getColumnEnum());
            }

            String columnType = handle.getColumnType(columnInfo);
            columnInfo.setDataType(columnType);
            return columnInfo;
        }).collect(Collectors.toList());
    }

    /**
     * 根据通用表信息创建表对象
     *
     * @param tableInfo
     * @param targetDatasource
     * @param deleteSourceTable
     * @return
     * @author 王瑞
     * @date 2023/8/21
     */
    @Override
    public void creatTable(TableInfo tableInfo, ReportDatasource targetDatasource, boolean deleteSourceTable) {
        new PostgreSQLCreateTableHandle().creatTable(tableInfo, targetDatasource);
    }

    /**
     * 将源信息转换成通用表数据
     *
     * @param sourceDatasource
     * @param model
     * @param tableViewName
     * @param tableComment
     * @return {@link TableInfo}
     * @author 王瑞
     * @date 2023/8/21
     */
    @Override
    public TableInfo parseTableInfo(ReportDatasource sourceDatasource, List<GeneralModel> model, String tableViewName, String tableComment) {
        return new PostgreSQLParseTableHandle().parseTableInfo(sourceDatasource, model, tableViewName, tableComment);
    }

    /**
     * 获取原表字段信息
     *
     * @param tableViewName
     * @param datasource
     * @return {@link List< ColumnInfo>}
     * @author 王瑞
     * @date 2023/12/25
     */
    @Override
    @SneakyThrows
    public List<ColumnInfo> getSourceColumn(String tableViewName, ReportDatasource datasource) throws SQLException {
        Connection connection = DynamicDataSourceSupport.createConnection(datasource);

        List<ColumnInfo> sourceColumn;
        try {
            sourceColumn = new PostgreSQLParseTableHandle().getSourceColumn(tableViewName, connection.getMetaData(), datasource.getDbSchema());
        } finally {
            connection.close();
        }
        return sourceColumn;

    }

    /**
     * 数据源类型
     *
     * @return
     */
    @Override
    public DsTypeEnum dsType() {
        return DsTypeEnum.postgresql;
    }
}
