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

import cn.hutool.core.io.IoUtil;
import cn.stylefeng.roses.kernel.db.api.pojo.druid.DruidProperties;
import cn.stylefeng.roses.kernel.dsctn.api.constants.DatasourceContainerConstants;
import cn.stylefeng.roses.kernel.dsctn.context.DataSourceContext;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.meta.api.pojo.db.DatabaseMetadataRequest;
import cn.stylefeng.team.meta.modular.enums.MetaModelExceptionEnum;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class DatabaseConnectionContext {

    public static DatabaseMetadataRequest currentDatabaseInfo() {

        Map<String, DruidProperties> dataSourcesConfs = DataSourceContext.getDataSourcesConfs();
        DruidProperties druidProperties = dataSourcesConfs.get(DatasourceContainerConstants.MASTER_DATASOURCE_NAME);

        DatabaseMetadataRequest databaseMetadataRequest = new DatabaseMetadataRequest();
        databaseMetadataRequest.setDatabaseUrl(druidProperties.getUrl());
        databaseMetadataRequest.setDatabaseUserName(druidProperties.getUsername());
        databaseMetadataRequest.setDatabasePassword(druidProperties.getPassword());
        return databaseMetadataRequest;
    }

    public static void executeUpdateSql(String sql) {
        Map<String, DataSource> dataSources = DataSourceContext.getDataSources();
        DataSource dataSource = dataSources.get(DatasourceContainerConstants.MASTER_DATASOURCE_NAME);

        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            connection.prepareStatement(sql).executeUpdate();
        } catch (SQLException e) {
            log.error("SQL执行出错，请检查系统配置", e);
            throw new ServiceException(MetaModelExceptionEnum.UPDATE_SQL_ERROR);
        } finally {
            IoUtil.close(connection);
        }
    }

    public static int executeCountSql(String sql) {
        Map<String, DataSource> dataSources = DataSourceContext.getDataSources();
        DataSource dataSource = dataSources.get(DatasourceContainerConstants.MASTER_DATASOURCE_NAME);

        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            ResultSet resultSet = connection.prepareStatement(sql).executeQuery(sql);

            if (resultSet.next()) {
                return resultSet.getInt("totalCount");
            } else {
                return 0;
            }

        } catch (SQLException e) {
            log.error("SQL执行出错，请检查系统配置", e);
            throw new ServiceException(MetaModelExceptionEnum.UPDATE_SQL_ERROR);
        } finally {
            IoUtil.close(connection);
        }
    }

    public static List<Map<String, Object>> executePageSql(String sql) {
        Map<String, DataSource> dataSources = DataSourceContext.getDataSources();
        DataSource dataSource = dataSources.get(DatasourceContainerConstants.MASTER_DATASOURCE_NAME);

        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            ResultSet resultSet = connection.prepareStatement(sql).executeQuery(sql);
            return resultSetToList(resultSet);
        } catch (SQLException e) {
            log.error("SQL执行出错，请检查系统配置", e);
            throw new ServiceException(MetaModelExceptionEnum.UPDATE_SQL_ERROR);
        } finally {
            IoUtil.close(connection);
        }
    }

    public static List<Map<String, Object>> resultSetToList(ResultSet rs) throws SQLException {
        ResultSetMetaData md = rs.getMetaData();
        int columns = md.getColumnCount();
        List<Map<String, Object>> list = new ArrayList<>();
        while (rs.next()) {
            Map<String, Object> row = new HashMap<>(columns);
            for (int i = 1; i <= columns; ++i) {
                row.put(md.getColumnLabel(i), rs.getObject(i));
            }
            list.add(row);
        }
        return list;
    }

}
