/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.config
 * @ClassName: DatabaseInitializer
 * @Description: 数据库初始化器，用于在应用启动时创建数据库（已迁移到DataSourceConfig）
 * @Author: 张志锋
 * @Date: 2025-10-31
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * 数据库初始化配置类
 * 用于自动创建不存在的数据库
 * 在数据源Bean创建之前执行初始化
 */
@Component
@ConditionalOnProperty(name = "spring.datasource.url")
public class DatabaseInitializer {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseInitializer.class);

    @Value("${spring.datasource.url}")
    private String pgsqlUrl;

    @Value("${spring.datasource.username:postgres}")
    private String pgsqlUsername;

    @Value("${spring.datasource.password}")
    private String pgsqlPassword;

    /**
     * 应用启动后自动初始化数据库
     * 使用@PostConstruct确保在Bean初始化时立即执行
     */
    @PostConstruct
    public void initializeDatabase() {
        try {
            // 解析数据库名称
            String databaseName = extractDatabaseName(pgsqlUrl);
            if (databaseName == null) {
                logger.warn("无法从PostgreSQL URL中解析数据库名称，跳过自动创建");
                return;
            }

            // 连接到默认的postgres数据库
            String defaultUrl = pgsqlUrl.replace("/" + databaseName, "/postgres");
            
            logger.info("正在检查PostgreSQL数据库 '{}' 是否存在...", databaseName);
            
            try (Connection conn = DriverManager.getConnection(defaultUrl, pgsqlUsername, pgsqlPassword)) {
                // 检查数据库是否存在
                String checkSql = "SELECT 1 FROM pg_database WHERE datname = ?";
                try (PreparedStatement stmt = conn.prepareStatement(checkSql)) {
                    stmt.setString(1, databaseName);
                    try (ResultSet rs = stmt.executeQuery()) {
                        if (!rs.next()) {
                            // 数据库不存在，创建它
                            logger.info("数据库 '{}' 不存在，正在创建...", databaseName);
                            
                            // PostgreSQL不允许在事务中执行CREATE DATABASE
                            // CREATE DATABASE不能使用PreparedStatement，需要使用Statement
                            conn.setAutoCommit(true);
                            String createSql = "CREATE DATABASE \"" + databaseName + "\"";
                            try (Statement createStmt = conn.createStatement()) {
                                createStmt.execute(createSql);
                                logger.info("数据库 '{}' 创建成功！", databaseName);
                            }
                        } else {
                            logger.info("数据库 '{}' 已存在，跳过创建", databaseName);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.warn("自动创建PostgreSQL数据库失败: {}", e.getMessage());
            logger.debug("详细信息", e);
        }
    }

    /**
     * 从JDBC URL中提取数据库名称
     * 
     * @param url JDBC URL，例如：jdbc:postgresql://localhost:5432/database_name
     * @return 数据库名称
     */
    private String extractDatabaseName(String url) {
        try {
            // 格式：jdbc:postgresql://host:port/database_name
            int lastSlash = url.lastIndexOf('/');
            if (lastSlash > 0 && lastSlash < url.length() - 1) {
                String dbPart = url.substring(lastSlash + 1);
                // 移除可能的查询参数
                int questionMark = dbPart.indexOf('?');
                if (questionMark > 0) {
                    return dbPart.substring(0, questionMark);
                }
                return dbPart;
            }
        } catch (Exception e) {
            logger.error("解析数据库名称失败", e);
        }
        return null;
    }
}

