package com.njcn.gather.systemops.database.component;

import cn.hutool.core.util.StrUtil;
import com.njcn.gather.systemops.database.constant.DatabaseOpsConst;
import com.njcn.gather.systemops.database.pojo.po.DatabaseConnection;
import com.njcn.gather.systemops.database.pojo.vo.DatabaseTableVO;
import com.njcn.gather.systemops.database.pojo.vo.DatabaseTestResultVO;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * Oracle JDBC 连接与元数据探测组件。
 */
@Component
public class OracleJdbcComponent {

    public DatabaseTestResultVO test(DatabaseConnection connection, String password) {
        DatabaseTestResultVO result = new DatabaseTestResultVO();
        try (Connection ignored = openConnection(connection, password)) {
            result.setSuccess(true);
            result.setMessage("连接成功");
        } catch (Exception exception) {
            result.setSuccess(false);
            result.setMessage(exception.getMessage());
        }
        return result;
    }

    public List<DatabaseTableVO> listTables(DatabaseConnection connection, String password, String schemaName) throws Exception {
        String owner = StrUtil.blankToDefault(schemaName, connection.getSchemaName());
        if (StrUtil.isBlank(owner)) {
            owner = connection.getUsername();
        }
        owner = owner.trim().toUpperCase(Locale.ROOT);
        String sql = "SELECT t.owner, t.table_name, t.num_rows, o.last_ddl_time, c.comments "
                + "FROM all_tables t "
                + "LEFT JOIN all_tab_comments c "
                + "ON t.owner = c.owner AND t.table_name = c.table_name "
                + "LEFT JOIN all_objects o "
                + "ON t.owner = o.owner AND t.table_name = o.object_name AND o.object_type = 'TABLE' "
                + "WHERE t.owner = ? ORDER BY t.table_name";
        try (Connection jdbcConnection = openConnection(connection, password);
             PreparedStatement statement = jdbcConnection.prepareStatement(sql)) {
            statement.setString(1, owner);
            try (ResultSet resultSet = statement.executeQuery()) {
                List<DatabaseTableVO> result = new ArrayList<>();
                while (resultSet.next()) {
                    DatabaseTableVO table = new DatabaseTableVO();
                    table.setOwner(resultSet.getString("owner"));
                    table.setTableName(resultSet.getString("table_name"));
                    table.setEngine(DatabaseOpsConst.DB_TYPE_ORACLE);
                    table.setTableRows(getLongValue(resultSet, "num_rows"));
                    Timestamp updateTime = resultSet.getTimestamp("last_ddl_time");
                    table.setUpdateTime(updateTime == null ? null : updateTime.toLocalDateTime());
                    table.setComments(resultSet.getString("comments"));
                    result.add(table);
                }
                return result;
            }
        }
    }

    private Long getLongValue(ResultSet resultSet, String columnName) throws Exception {
        long value = resultSet.getLong(columnName);
        return resultSet.wasNull() ? null : value;
    }

    public Connection openConnection(DatabaseConnection connection, String password) throws Exception {
        if (StrUtil.isBlank(password)) {
            throw new IllegalArgumentException("数据库密码不能为空");
        }
        return DriverManager.getConnection(buildJdbcUrl(connection), connection.getUsername(), password);
    }

    public String buildJdbcUrl(DatabaseConnection connection) {
        if (DatabaseOpsConst.CONNECT_TYPE_SID.equalsIgnoreCase(connection.getConnectType())) {
            return "jdbc:oracle:thin:@" + connection.getHost() + ":" + connection.getPort() + ":" + connection.getSid();
        }
        return "jdbc:oracle:thin:@//" + connection.getHost() + ":" + connection.getPort() + "/" + connection.getServiceName();
    }
}
