//! Module pour la gestion des variables d'environnement requises
//!
//! Ce module fournit des fonctions helper pour récupérer des variables d'environnement
//! avec validation stricte. L'application refuse de démarrer si les secrets requis
//! ne sont pas définis.

use std::env;

/// Récupère une variable d'environnement requise.
///
/// Panic si la variable n'est pas définie ou est vide.
///
/// # Arguments
///
/// * `key` - Le nom de la variable d'environnement
///
/// # Panics
///
/// Panic avec un message d'erreur clair si la variable n'est pas définie.
///
/// # Example
///
/// ```rust,should_panic
/// # use chat_server::env::require_env;
/// // Panic si JWT_SECRET n'est pas défini
/// let secret = require_env("JWT_SECRET");
/// ```
pub fn require_env(key: &str) -> String {
    env::var(key).unwrap_or_else(|_| {
        panic!(
            "FATAL: Required environment variable {} is not set. \
             Application cannot start without this configuration.",
            key
        )
    })
}

/// Récupère une variable d'environnement requise avec validation de longueur minimale.
///
/// Utile pour les secrets qui doivent avoir une certaine complexité.
///
/// # Arguments
///
/// * `key` - Le nom de la variable d'environnement
/// * `min_length` - Longueur minimale requise
///
/// # Panics
///
/// Panic si la variable n'est pas définie ou si sa longueur est inférieure à `min_length`.
///
/// # Example
///
/// ```rust,should_panic
/// # use chat_server::env::require_env_min_length;
/// // Panic si JWT_SECRET n'est pas défini ou fait moins de 32 caractères
/// let secret = require_env_min_length("JWT_SECRET", 32);
/// ```
pub fn require_env_min_length(key: &str, min_length: usize) -> String {
    let value = require_env(key);
    if value.len() < min_length {
        panic!(
            "FATAL: Environment variable {} must be at least {} characters long (got {})",
            key,
            min_length,
            value.len()
        )
    }
    value
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::panic;

    #[test]
    fn test_require_env_panics_on_missing() {
        let key = "TEST_NONEXISTENT_VAR_12345";
        env::remove_var(key);

        let result = panic::catch_unwind(|| require_env(key));

        assert!(
            result.is_err(),
            "require_env should panic on missing variable"
        );
    }

    #[test]
    fn test_require_env_returns_value_when_set() {
        let key = "TEST_EXISTING_VAR";
        let value = "test_value_123";
        env::set_var(key, value);

        let result = require_env(key);
        assert_eq!(result, value);

        env::remove_var(key);
    }

    #[test]
    fn test_require_env_min_length_panics_on_short() {
        let key = "TEST_SHORT_SECRET";
        env::set_var(key, "short");

        let result = panic::catch_unwind(|| require_env_min_length(key, 32));

        env::remove_var(key);
        assert!(
            result.is_err(),
            "require_env_min_length should panic on short value"
        );
    }

    #[test]
    fn test_require_env_min_length_returns_value_when_valid() {
        let key = "TEST_LONG_SECRET";
        let value = "this_is_a_long_secret_key_that_meets_the_minimum_length_requirement";
        env::set_var(key, value);

        let result = require_env_min_length(key, 32);
        assert_eq!(result, value);

        env::remove_var(key);
    }
}
