//! Gestionnaire de connection pool PostgreSQL pour stream server
//!
//! Ce module fournit des fonctions pour créer et configurer un pool de connexions
//! PostgreSQL optimisé pour le stream server.

use crate::config::DatabaseConfig;
use sqlx::postgres::PgPoolOptions;
use sqlx::PgPool;
use std::time::Duration;
// Note: Use tracing::info! macro directly instead of importing

/// Crée un pool de connexions PostgreSQL avec configuration optimale
///
/// # Arguments
///
/// * `database_url` - URL de connexion à la base de données PostgreSQL
///
/// # Returns
///
/// Un `PgPool` configuré ou une erreur si la connexion échoue
///
/// # Configuration par défaut
///
/// - `max_connections`: 10 connexions maximum
/// - `min_connections`: 1 connexion minimum maintenue
/// - `acquire_timeout`: 30 secondes pour acquérir une connexion
/// - `idle_timeout`: 600 secondes (10 minutes) avant fermeture d'une connexion inactive
/// - `max_lifetime`: 3600 secondes (1 heure) durée de vie maximale d'une connexion
///
/// # Exemple
///
/// ```rust,no_run
/// use stream_server::database::pool::create_pool;
///
/// #[tokio::main]
/// async fn main() {
///     let database_url = "postgresql://user:password@localhost/veza_db";
///     let pool = create_pool(database_url).await.expect("Failed to create pool");
///     // Utiliser le pool...
/// }
/// ```
pub async fn create_pool(database_url: &str) -> Result<PgPool, sqlx::Error> {
    PgPoolOptions::new()
        .max_connections(10)
        .min_connections(1)
        .acquire_timeout(Duration::from_secs(30))
        .idle_timeout(Duration::from_secs(600))
        .max_lifetime(Duration::from_secs(3600))
        .connect(database_url)
        .await
}

/// Crée un pool de connexions PostgreSQL depuis une configuration
///
/// # Arguments
///
/// * `config` - Configuration de la base de données
///
/// # Returns
///
/// Un `PgPool` configuré ou une erreur si la connexion échoue
///
/// # Configuration
///
/// Utilise les paramètres de `DatabaseConfig` :
/// - `max_connections`: Nombre maximum de connexions
/// - `min_connections`: Nombre minimum de connexions maintenues
/// - `connection_timeout`: Timeout pour acquérir une connexion
/// - `idle_timeout`: Timeout avant fermeture d'une connexion inactive
/// - `max_lifetime`: Durée de vie maximale d'une connexion
///
/// # Exemple
///
/// ```rust,no_run
/// use stream_server::database::pool::create_pool_from_config;
/// use stream_server::config::Config;
///
/// #[tokio::main]
/// async fn main() {
///     let config = Config::from_env().unwrap();
///     let pool = create_pool_from_config(&config.database).await
///         .expect("Failed to create pool");
///     // Utiliser le pool...
/// }
/// ```
pub async fn create_pool_from_config(config: &DatabaseConfig) -> Result<PgPool, sqlx::Error> {
    tracing::info!(
        "🔌 Création du pool de connexions PostgreSQL: {} (max: {}, min: {})",
        config.url,
        config.max_connections,
        config.min_connections
    );

    let pool = PgPoolOptions::new()
        .max_connections(config.max_connections)
        .min_connections(config.min_connections)
        .acquire_timeout(config.connection_timeout)
        .idle_timeout(Some(config.idle_timeout))
        .max_lifetime(Some(config.max_lifetime))
        .connect(&config.url)
        .await?;

    tracing::debug!(
        "✅ Pool de connexions créé: max={}, min={}, timeout={:?}",
        config.max_connections,
        config.min_connections,
        config.connection_timeout
    );

    Ok(pool)
}

/// Crée un pool de connexions avec une URL depuis une variable d'environnement
///
/// # Arguments
///
/// * `env_var` - Nom de la variable d'environnement contenant l'URL (par défaut "DATABASE_URL")
///
/// # Returns
///
/// Un `PgPool` configuré ou une erreur si la connexion échoue
pub async fn create_pool_from_env(env_var: Option<&str>) -> Result<PgPool, sqlx::Error> {
    let var_name = env_var.unwrap_or("DATABASE_URL");
    let database_url = std::env::var(var_name).map_err(|_| {
        sqlx::Error::Configuration(format!("Environment variable {} not set", var_name).into())
    })?;
    create_pool(&database_url).await
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::config::DatabaseConfig;

    #[tokio::test]
    #[ignore] // Nécessite une base de données de test
    async fn test_create_pool() {
        let database_url = std::env::var("TEST_DATABASE_URL")
            .unwrap_or_else(|_| "postgresql://localhost/veza_test".to_string());
        let pool = create_pool(&database_url).await;
        assert!(pool.is_ok(), "Pool creation should succeed");
    }

    #[tokio::test]
    #[ignore] // Nécessite une base de données de test
    async fn test_create_pool_from_env() {
        std::env::set_var("TEST_DATABASE_URL", "postgresql://localhost/veza_test");
        let pool = create_pool_from_env(Some("TEST_DATABASE_URL")).await;
        // Note: Le test peut échouer si la DB n'est pas disponible, c'est OK
        if pool.is_ok() {
            println!("✅ Pool créé avec succès");
        } else {
            println!("⚠️ Pool non créé (DB non disponible)");
        }
    }

    #[test]
    fn test_create_pool_from_config_structure() {
        // Test que la structure de configuration est correcte
        let config = DatabaseConfig {
            url: "postgresql://test".to_string(),
            max_connections: 10,
            min_connections: 1,
            connection_timeout: Duration::from_secs(30),
            idle_timeout: Duration::from_secs(600),
            max_lifetime: Duration::from_secs(3600),
            enable_logging: false,
            migrate_on_start: false,
        };

        assert_eq!(config.max_connections, 10);
        assert_eq!(config.min_connections, 1);
        assert!(!config.url.is_empty());
    }
}
