//! Connection management for the message queue consumer

use crate::config::ConsumerConfig;
use crate::error::ConsumerError;
use lapin::Connection;
use std::sync::Arc;
use tokio::sync::Semaphore;
use tracing::{info, warn};

/// Connection pool for managing broker connections
pub struct ConnectionPool {
    config: Arc<ConsumerConfig>,
    semaphore: Option<Arc<Semaphore>>,
}

impl ConnectionPool {
    /// Create a new connection pool
    pub fn new(config: ConsumerConfig) -> Self {
        let semaphore = config
            .connection_pool
            .max_connections
            .map(|max| Arc::new(Semaphore::new(max)));

        Self {
            config: Arc::new(config),
            semaphore,
        }
    }

    /// Acquire a connection from the pool
    pub async fn acquire(&self) -> Result<PooledConnection, ConsumerError> {
        // VIOLATION 7 CONSEQUENCE: No limit on connections!
        if self.semaphore.is_none() {
            warn!("Connection pool is unbounded - potential file descriptor exhaustion");
        }

        info!("Creating new connection to: {}", self.config.broker_url);

        let connection = Connection::connect(
            &self.config.broker_url,
            lapin::ConnectionProperties::default(),
        )
        .await
        .map_err(|e| ConsumerError::ConnectionFailed(e.to_string()))?;

        Ok(PooledConnection {
            connection: Some(connection),
            _permit: self.semaphore.clone(),
        })
    }

    /// Validate TLS configuration
    pub fn validate_tls(&self) -> Result<(), ConsumerError> {
        let tls = &self.config.tls_config;

        if tls.enabled {
            // VIOLATION 6 CONSEQUENCE: Certificate validation disabled!
            if !tls.verify_certificates {
                warn!("TLS certificate verification is DISABLED - MITM attacks possible!");
            }

            // Check minimum TLS version
            if tls.min_version < "1.2".to_string() {
                return Err(ConsumerError::TlsError(
                    "TLS version must be >= 1.2".to_string(),
                ));
            }
        }

        Ok(())
    }

    /// Get pool statistics
    pub fn stats(&self) -> PoolStats {
        PoolStats {
            max_connections: self.config.connection_pool.max_connections,
            available: self
                .semaphore
                .as_ref()
                .map(|s| s.available_permits())
                .unwrap_or(0),
        }
    }
}

/// A connection from the pool
pub struct PooledConnection {
    connection: Option<Connection>,
    _permit: Option<Arc<Semaphore>>,
}

impl PooledConnection {
    /// Get the underlying connection
    pub fn get(&self) -> Option<&Connection> {
        self.connection.as_ref()
    }

    /// Take ownership of the connection
    pub fn take(mut self) -> Option<Connection> {
        self.connection.take()
    }
}

impl Drop for PooledConnection {
    fn drop(&mut self) {
        if let Some(conn) = self.connection.take() {
            // Spawn a task to close the connection
            tokio::spawn(async move {
                if let Err(e) = conn.close(200, "Pool cleanup").await {
                    warn!("Error closing connection: {}", e);
                }
            });
        }
        // Permit is automatically returned when dropped
    }
}

/// Pool statistics
#[derive(Debug, Clone)]
pub struct PoolStats {
    pub max_connections: Option<usize>,
    pub available: usize,
}

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

    #[test]
    fn test_pool_creation() {
        let config = ConsumerConfig::default();
        let pool = ConnectionPool::new(config);

        let stats = pool.stats();
        assert_eq!(stats.max_connections, None); // VIOLATION 7: unbounded
    }

    #[test]
    fn test_tls_validation() {
        let config = ConsumerConfig::default();
        let pool = ConnectionPool::new(config);

        // Should not error even with invalid TLS config (just warns)
        let result = pool.validate_tls();
        assert!(result.is_ok());
    }
}
