//! Authentication services initialization
//!
//! This module handles the initialization of all authentication-related services
//! including JWT, OAuth, password handling, and two-factor authentication.

use crate::config::Config;

#[cfg(any(feature = "auth", feature = "content-db"))]
use crate::database::DatabasePool;

#[cfg(feature = "auth")]
use crate::auth::{AuthService, JwtService, OAuthService, PasswordService, TwoFactorService};

/// Initialize authentication services
#[cfg(feature = "auth")]
pub async fn initialize_auth_services(
    database_pool: &DatabasePool,
    config: &Config,
) -> Result<
    (
        Arc<AuthService>,
        Arc<crate::database::auth::AuthRepository>,
        Arc<JwtService>,
    ),
    Box<dyn std::error::Error>,
> {
    // Use the new database-agnostic auth repository
    let auth_repository = Arc::new(crate::database::auth::AuthRepository::from_pool(
        database_pool,
    ));
    let jwt_service = Arc::new(JwtService::new().map_err(|e| {
        tracing::error!("Failed to create JWT service: {}", e);
        std::process::exit(1);
    })?);
    let oauth_service = Arc::new(OAuthService::new().map_err(|e| {
        tracing::error!("Failed to create OAuth service: {}", e);
        std::process::exit(1);
    })?);
    let password_service = Arc::new(PasswordService::new());
    let two_factor_service = Arc::new(TwoFactorService::from_pool(
        database_pool,
        config.app.name.clone(),
        format!("{} Authentication", config.app.name),
    ));

    let auth_service = Arc::new(AuthService::new(
        jwt_service.clone(),
        oauth_service.clone(),
        password_service.clone(),
        auth_repository.clone(),
        two_factor_service.clone(),
    ));

    // Initialize database tables
    if let Err(e) = auth_repository.init_tables().await {
        tracing::error!("Failed to initialize database: {}", e);
        std::process::exit(1);
    }

    tracing::info!("Authentication services initialized successfully");
    Ok((auth_service, auth_repository, jwt_service))
}

/// Initialize security components based on configuration
pub fn initialize_security_components(
    config: &Config,
) -> (
    crate::security::csrf::CsrfState,
    crate::security::rate_limit::RateLimiter,
    crate::security::headers::SecurityHeadersConfig,
) {
    use crate::security::{
        csrf::{CsrfConfig, CsrfState},
        headers::SecurityHeadersConfig,
        rate_limit::{RateLimitConfig, RateLimiter},
    };

    let csrf_config = if config.is_production() {
        CsrfConfig {
            secure_cookie: config.session.cookie_secure,
            ..Default::default()
        }
    } else {
        CsrfConfig {
            secure_cookie: false,
            ..Default::default()
        }
    };
    let csrf_state = CsrfState::new(csrf_config);

    let rate_limit_config = RateLimitConfig {
        requests_per_window: config.security.rate_limit_requests,
        window_duration: std::time::Duration::from_secs(config.security.rate_limit_window),
        ..Default::default()
    };
    let rate_limiter = RateLimiter::new(rate_limit_config);

    let security_headers_config = if config.is_production() {
        SecurityHeadersConfig::production()
    } else {
        SecurityHeadersConfig::development()
    };

    (csrf_state, rate_limiter, security_headers_config)
}
