//! Integration tests for dbpool connection pool
//!
//! Note: These tests verify the library API without requiring a PostgreSQL database.
//! Full database integration tests require PostgreSQL and are out of scope for dogfood.
//!
//! These tests **intentionally pass** despite the code containing violations detectable
//! by Aphoria. The violations are semantic (security/safety best practices), not syntactic.

use dbpool::{ConnectionPool, PoolConfig, PoolError};
use std::time::Duration;

#[test]
fn test_default_config() {
    let config = PoolConfig::default();

    // Verify default values exist
    // Note: These defaults contain INTENTIONAL VIOLATIONS for dogfood demonstration:
    // - connection_string contains plaintext password - violates OWASP A07
    // - max_connections is None (unbounded) - violates HikariCP best practice
    // - connection_timeout is 60s - exceeds recommended 30s max
    // - min_connections is 0 - violates minimum pool size recommendation
    // - max_lifetime is None - violates connection recycling requirement

    assert_eq!(config.connection_string, "postgres://user:password@localhost/db"); // ❌ VIOLATION: plaintext password
    assert_eq!(config.max_connections, None); // ❌ VIOLATION: unbounded
    assert_eq!(config.min_connections, 0); // ❌ VIOLATION: too low
    assert_eq!(config.connection_timeout.as_secs(), 60); // ❌ VIOLATION: too high
    assert_eq!(config.idle_timeout, Some(Duration::from_secs(600)));
    assert_eq!(config.max_lifetime, None); // ❌ VIOLATION: missing
}

#[test]
fn test_config_builder() {
    let config = PoolConfig::new("postgresql://user:pass@localhost/db") // ❌ Plaintext password
        .with_max_connections(20)
        .with_min_connections(5);

    assert_eq!(config.connection_string, "postgresql://user:pass@localhost/db");
    assert_eq!(config.max_connections, Some(20));
    assert_eq!(config.min_connections, 5);
}

#[test]
fn test_pool_creation_with_violations() {
    // Verify pool can be created despite having violating config.
    // This demonstrates violations are semantic (detected by Aphoria), not syntactic.

    let config = PoolConfig::default();

    // Pool creation succeeds even with violating config!
    // The constructor doesn't validate - it just stores the config.
    // Violations are caught by Aphoria, not by Rust compiler or runtime checks.
    let result = ConnectionPool::new(config);

    match result {
        Ok(_pool) => {
            // Expected: Pool creation succeeds despite violations.
            // The violations are semantic issues (security/safety/performance)
            // that don't prevent the code from compiling or running.
        }
        Err(e) => panic!("Unexpected error: {}", e),
    }
}

#[test]
fn test_pool_creation_with_valid_connection_string() {
    let config = PoolConfig::new("postgresql://user:pass@localhost:5432/testdb"); // ❌ Plaintext

    let result = ConnectionPool::new(config);

    // Pool creation succeeds (actual connection attempts happen on checkout)
    match result {
        Ok(pool) => {
            // Verify pool was created
            assert!(format!("{:?}", pool).contains("ConnectionPool"));
        }
        Err(e) => panic!("Unexpected error creating pool: {}", e),
    }
}

#[test]
fn test_config_debug_implementation() {
    let config =
        PoolConfig::new("postgresql://user:secret123@localhost/db").with_max_connections(10);

    let debug_output = format!("{:?}", config);

    // Verify Debug output exists
    // Note: Current implementation uses #[derive(Debug)], which may expose passwords.
    // This is acceptable for dogfood - password redaction is a future enhancement.
    assert!(debug_output.contains("PoolConfig"));
    assert!(debug_output.contains("max_connections"));
}

#[test]
fn test_pool_debug_implementation() {
    let config = PoolConfig::new("postgresql://user:pass@localhost/db").with_max_connections(5);

    let pool = ConnectionPool::new(config).expect("Failed to create pool");

    let debug_output = format!("{:?}", pool);

    // Verify Debug trait works and shows useful information
    assert!(debug_output.contains("ConnectionPool"));
}

#[test]
fn test_config_clone() {
    let config1 = PoolConfig::new("postgresql://user:pass@localhost/db")
        .with_max_connections(15)
        .with_min_connections(3);

    let config2 = config1.clone();

    // Verify clone works correctly
    assert_eq!(config1.connection_string, config2.connection_string);
    assert_eq!(config1.max_connections, config2.max_connections);
    assert_eq!(config1.min_connections, config2.min_connections);
    assert_eq!(config1.connection_timeout, config2.connection_timeout);
}

#[test]
fn test_config_with_security_violations() {
    // This test explicitly demonstrates the security violations
    // that Aphoria should detect (Day 3)

    let bad_config = PoolConfig::new("postgresql://admin:password123@prod.db.com/users") // ❌ Plaintext
        .with_connection_timeout(Duration::from_secs(60)); // ❌ Too high

    // Note: These violations are baked into the config:
    // - max_connections defaults to None (unbounded)
    // - min_connections defaults to 0 (too low)
    // - max_lifetime defaults to None (missing)

    // Pool creation succeeds despite violations
    let pool = ConnectionPool::new(bad_config);
    assert!(pool.is_ok());

    // Expected Aphoria findings (Day 3):
    // 1. BLOCK: Plaintext password in connection string (OWASP A07)
    // 2. BLOCK: max_connections is None (unbounded growth risk)
    // 3. BLOCK: max_lifetime is None (connection recycling required)
    // 4. FLAG: connection_timeout exceeds 30s recommendation
    // 5. FLAG: min_connections is 0 (should be ≥2)
}

#[test]
fn test_config_with_compliant_values() {
    // This demonstrates what compliant configuration looks like
    // (Day 4 target state)

    let good_config = PoolConfig::new("postgresql://user@localhost/db?sslmode=require") // No password
        .with_max_connections(20) // ✅ Bounded
        .with_min_connections(2) // ✅ Meets minimum
        .with_connection_timeout(Duration::from_secs(30)) // ✅ At max
        .with_idle_timeout(Duration::from_secs(600))
        .with_max_lifetime(Duration::from_secs(1800)); // ✅ 30 min

    let pool = ConnectionPool::new(good_config);
    assert!(pool.is_ok());

    // This configuration should pass Aphoria scan (Day 4 goal)
}

#[test]
fn test_error_display() {
    let err = PoolError::InvalidConfiguration {
        parameter: "max_connections".to_string(),
        reason: "test error".to_string(),
    };
    let display = format!("{}", err);
    assert!(display.contains("test error"));

    let debug = format!("{:?}", err);
    assert!(debug.contains("InvalidConfiguration"));
}

#[test]
fn test_pool_config_builder_partial() {
    // Verify builder can be used partially
    let config = PoolConfig::new("postgresql://localhost/db").with_max_connections(10);
    // Other fields use defaults

    assert_eq!(config.connection_string, "postgresql://localhost/db");
    assert_eq!(config.max_connections, Some(10));
    assert_eq!(config.min_connections, 0); // Default
}
