//! Integration tests for PostgreSQL Manager
//!
//! Note: These tests require SSH access to a test server.
//! Set the following environment variables to run these tests:
//! - TEST_SSH_HOST: SSH server hostname or IP
//! - TEST_SSH_USER: SSH username
//! - TEST_SSH_PASSWORD: SSH password (or use TEST_SSH_KEY_PATH)
//! - TEST_SSH_KEY_PATH: SSH private key path (alternative to password)
//!
//! Example:
//! ```bash
//! export TEST_SSH_HOST=192.168.1.100
//! export TEST_SSH_USER=root
//! export TEST_SSH_PASSWORD=secret
//! cargo test --test integration_tests -- --ignored
//! ```

use lmrc_postgres::{PostgresConfig, PostgresManager};
use std::env;

/// Helper to check if integration tests should run
fn should_run_integration_tests() -> bool {
    env::var("TEST_SSH_HOST").is_ok()
}

/// Get test server configuration from environment
fn get_test_config() -> (String, String, Option<String>, Option<String>) {
    let host = env::var("TEST_SSH_HOST").expect("TEST_SSH_HOST not set");
    let user = env::var("TEST_SSH_USER").unwrap_or_else(|_| "root".to_string());
    let password = env::var("TEST_SSH_PASSWORD").ok();
    let key_path = env::var("TEST_SSH_KEY_PATH").ok();

    (host, user, password, key_path)
}

/// Build a test PostgresManager
fn build_test_manager() -> PostgresManager {
    let (host, user, password, key_path) = get_test_config();

    let config = PostgresConfig::builder()
        .version("15")
        .database_name("test_db")
        .username("test_user")
        .password("test_password")
        .listen_addresses("0.0.0.0/0")
        .port(5432)
        .build()
        .expect("Failed to build config");

    let mut builder = PostgresManager::builder()
        .config(config)
        .server_ip(host)
        .ssh_user(user);

    if let Some(pwd) = password {
        builder = builder.ssh_password(pwd);
    } else if let Some(key) = key_path {
        builder = builder.ssh_key_path(key);
    }

    builder.build().expect("Failed to build manager")
}

#[tokio::test]
#[ignore] // Run with: cargo test --test integration_tests -- --ignored
async fn test_full_lifecycle() {
    if !should_run_integration_tests() {
        eprintln!("Skipping integration test - TEST_SSH_HOST not set");
        return;
    }

    let manager = build_test_manager();

    // Test installation
    println!("Testing installation...");
    manager.install().await.expect("Installation failed");

    // Verify installation
    let installed = manager.is_installed().await.expect("Check failed");
    assert!(installed, "PostgreSQL should be installed");

    // Get version
    let version = manager
        .get_installed_version()
        .await
        .expect("Version check failed");
    assert_eq!(version, Some("15".to_string()));

    // Test configuration
    println!("Testing configuration...");
    manager.configure().await.expect("Configuration failed");

    // Test connection
    println!("Testing connection...");
    manager
        .test_connection()
        .await
        .expect("Connection test failed");

    // Test uninstall
    println!("Testing uninstall...");
    manager.uninstall(true).await.expect("Uninstall failed");

    // Verify uninstallation
    let installed = manager.is_installed().await.expect("Check failed");
    assert!(!installed, "PostgreSQL should be uninstalled");

    println!("Full lifecycle test completed successfully!");
}

#[tokio::test]
#[ignore]
async fn test_idempotent_installation() {
    if !should_run_integration_tests() {
        return;
    }

    let manager = build_test_manager();

    // Install once
    manager.install().await.expect("First installation failed");

    // Install again (should be idempotent)
    manager.install().await.expect("Second installation failed");

    // Verify still installed
    let installed = manager.is_installed().await.expect("Check failed");
    assert!(installed);

    // Cleanup
    manager.uninstall(true).await.ok();
}

#[tokio::test]
#[ignore]
async fn test_diff_detection() {
    if !should_run_integration_tests() {
        return;
    }

    let manager = build_test_manager();

    // Install and configure
    manager.setup().await.expect("Setup failed");

    // Get diff (should be empty)
    let diff = manager.diff().await.expect("Diff failed");
    println!("Diff: {}", diff);

    // Cleanup
    manager.uninstall(true).await.ok();
}
