//! # RUSTELO Server Binary
//!
//! <div align="center">
//!   <img src="../logos/rustelo_dev-logo-h.svg" alt="RUSTELO" width="300" />
//! </div>
//!
//! Main server executable for the RUSTELO web application framework.
//!
//! ## Overview
//!
//! This is the main entry point for the RUSTELO server application. It initializes all services,
//! sets up routing, configures middleware, and starts the web server with support for:
//!
//! - **Authentication & Authorization** - JWT tokens, OAuth2, 2FA, RBAC
//! - **Content Management** - Markdown processing, media handling, database storage
//! - **Email Services** - Multi-provider email with templating
//! - **Security** - CSRF protection, rate limiting, HTTPS/TLS
//! - **Performance** - Metrics collection, connection pooling, caching
//!
//! ## Features
//!
//! ### Core Features (Always Available)
//! - **HTTP Server** - Fast Axum-based web server
//! - **Static Files** - Efficient static file serving
//! - **Health Checks** - Server health monitoring
//! - **CSRF Protection** - Cross-site request forgery protection
//! - **Rate Limiting** - Request rate limiting and throttling
//! - **Security Headers** - Comprehensive security headers
//!
//! ### Optional Features (Feature-Gated)
//! - **`auth`** - Complete authentication system with JWT, OAuth2, 2FA
//! - **`content-db`** - Database-backed content management
//! - **`email`** - Email sending with multiple providers
//! - **`tls`** - HTTPS/TLS encryption support
//! - **`metrics`** - Performance monitoring and metrics collection
//!
//! ## Usage
//!
//! ```bash
//! # Start with default configuration
//! cargo run
//!
//! # Start with specific features
//! cargo run --features "auth,content-db,email,tls"
//!
//! # Start with custom configuration
//! RUSTELO_CONFIG=custom.toml cargo run
//! ```
//!
//! ## Configuration
//!
//! The server can be configured through:
//! - Environment variables (prefixed with `RUSTELO_`)
//! - TOML configuration files
//! - Command-line arguments
//! - Default values with sensible fallbacks
//!
//! ### Example Configuration
//!
//! ```toml
//! [server]
//! host = "127.0.0.1"
//! port = 3030
//! protocol = "https"
//!
//! [database]
//! url = "postgresql://user:pass@localhost/rustelo"
//! max_connections = 10
//!
//! [auth]
//! jwt_secret = "your-secret-key"
//! jwt_expiration_hours = 24
//! enable_2fa = true
//!
//! [email]
//! provider = "smtp"
//! from_address = "noreply@rustelo.dev"
//! ```
//!
//! ## Architecture
//!
//! The server follows a modular architecture with clear separation of concerns:
//!
//! ### Application State
//! - **Leptos Integration** - SSR options and hydration
//! - **Security Services** - CSRF protection and rate limiting
//! - **Authentication** - JWT service and user management
//! - **Content Services** - Content processing and storage
//! - **Email Services** - Email templating and delivery
//! - **Metrics** - Performance monitoring and collection
//!
//! ### Request Handling
//! - **Routing** - API endpoints and static file serving
//! - **Middleware** - Authentication, CORS, security headers
//! - **Error Handling** - Comprehensive error responses
//! - **Logging** - Structured logging with tracing
//!
//! ## Security
//!
//! The server implements multiple security layers:
//!
//! - **Memory Safety** - Rust's ownership system prevents vulnerabilities
//! - **Input Validation** - Comprehensive validation of all inputs
//! - **CSRF Protection** - Token-based CSRF protection
//! - **Rate Limiting** - Request throttling and abuse prevention
//! - **Security Headers** - HSTS, CSP, X-Frame-Options, etc.
//! - **TLS/HTTPS** - End-to-end encryption (when enabled)
//!
//! ## Performance
//!
//! Optimized for high performance:
//!
//! - **Async/Await** - Non-blocking I/O with Tokio
//! - **Connection Pooling** - Efficient database connections
//! - **Static File Caching** - Optimized static asset serving
//! - **Request Deduplication** - Efficient request handling
//! - **Metrics Collection** - Performance monitoring and optimization
//!
//! ## Monitoring
//!
//! Built-in monitoring capabilities:
//!
//! - **Health Endpoints** - `/health` for service monitoring
//! - **Metrics Collection** - Prometheus-compatible metrics
//! - **Structured Logging** - JSON-formatted logs for analysis
//! - **Error Tracking** - Comprehensive error reporting
//!
//! ## License
//!
//! This project is licensed under the MIT License - see the [LICENSE](https://github.com/yourusername/rustelo/blob/main/LICENSE) file for details.

// Suppress the leptos_router warning about reactive signal access
#![allow(unused_variables)]

#[cfg(feature = "auth")]
mod auth;
mod config;
#[cfg(feature = "content-db")]
mod content;
#[cfg(any(feature = "auth", feature = "content-db"))]
mod database;
#[cfg(feature = "email")]
mod email;
#[cfg(feature = "examples")]
mod examples;
mod handlers;
mod health;
#[cfg(feature = "metrics")]
mod metrics;
mod security;
#[cfg(feature = "content-db")]
mod template;

#[cfg(feature = "auth")]
use database::auth::AuthRepositoryTrait;
mod utils;

#[cfg(any(feature = "auth", feature = "content-db"))]
mod migrations;

use axum::{Router, extract::Request, middleware, middleware::Next, response::Response};
use client::app::{App, shell, shell_with_path};

#[cfg(feature = "auth")]
use auth::{
    AuthService, JwtService, OAuthService, PasswordService, TwoFactorService, auth_middleware,
    create_auth_routes,
};
use axum::http::HeaderValue;
use config::{Config, Protocol};
#[cfg(feature = "content-db")]
use content::{ContentRepository, ContentService, ContentSource, create_content_routes};
#[cfg(any(feature = "auth", feature = "content-db"))]
use database::{Database, DatabaseConfig, DatabasePool};
#[cfg(feature = "email")]
use email::{EmailService, EmailServiceBuilder};
#[cfg(feature = "email")]
use handlers::email::create_email_routes;
use health::create_health_routes;
use leptos::prelude::*;
use leptos_axum::{LeptosRoutes, generate_route_list};
#[cfg(feature = "metrics")]
use metrics::{MetricsService, create_metrics_routes, metrics_middleware};
use security::{
    csrf::{CsrfConfig, CsrfState},
    headers::{SecurityHeadersConfig, add_security_headers_with_config},
    rate_limit::{RateLimitConfig, RateLimiter},
};
#[cfg(any(feature = "auth", feature = "content-db"))]
use std::sync::Arc;
#[cfg(feature = "auth")]
use tower_cookies::CookieManagerLayer;
use tower_http::services::ServeDir;
use tracing_subscriber;

/// Middleware to add no-cache headers for development and fix MIME types
async fn dev_cache_middleware(request: Request, next: Next) -> Response {
    // Get the path before moving the request
    let path = request.uri().path().to_string();
    let mut response = next.run(request).await;

    // Set proper MIME types for static files
    if path.starts_with("/public/") {
        let headers = response.headers_mut();

        // Set proper content-type based on file extension
        if path.ends_with(".css") {
            headers.insert("Content-Type", HeaderValue::from_static("text/css"));
        } else if path.ends_with(".js") {
            headers.insert(
                "Content-Type",
                HeaderValue::from_static("application/javascript"),
            );
        } else if path.ends_with(".html") {
            headers.insert("Content-Type", HeaderValue::from_static("text/html"));
        } else if path.ends_with(".json") {
            headers.insert("Content-Type", HeaderValue::from_static("application/json"));
        } else if path.ends_with(".svg") {
            headers.insert("Content-Type", HeaderValue::from_static("image/svg+xml"));
        } else if path.ends_with(".png") {
            headers.insert("Content-Type", HeaderValue::from_static("image/png"));
        } else if path.ends_with(".jpg") || path.ends_with(".jpeg") {
            headers.insert("Content-Type", HeaderValue::from_static("image/jpeg"));
        }

        // Only add no-cache headers in development
        if cfg!(debug_assertions) {
            headers.insert(
                "Cache-Control",
                HeaderValue::from_static("no-cache, no-store, must-revalidate"),
            );
            headers.insert("Pragma", HeaderValue::from_static("no-cache"));
            headers.insert("Expires", HeaderValue::from_static("0"));
        }
    } else if cfg!(debug_assertions) && path.starts_with("/pkg/") {
        let headers = response.headers_mut();
        headers.insert(
            "Cache-Control",
            HeaderValue::from_static("no-cache, no-store, must-revalidate"),
        );
        headers.insert("Pragma", HeaderValue::from_static("no-cache"));
        headers.insert("Expires", HeaderValue::from_static("0"));
    }

    response
}

// Unified application state that works with Axum's single-state requirement
#[derive(Clone)]
pub struct AppState {
    pub leptos_options: LeptosOptions,
    pub csrf_state: CsrfState,
    pub rate_limiter: RateLimiter,
    #[cfg(feature = "auth")]
    pub auth_service: Arc<AuthService>,
    #[cfg(feature = "auth")]
    pub jwt_service: Arc<JwtService>,
    #[cfg(feature = "auth")]
    pub auth_repository: Arc<database::auth::AuthRepository>,
    #[cfg(feature = "content-db")]
    pub content_service: Arc<ContentService>,
    #[cfg(feature = "email")]
    pub email_service: Arc<EmailService>,
    #[cfg(feature = "metrics")]
    pub metrics_registry: Option<Arc<metrics::MetricsRegistry>>,
}

/// Main entry point for the Axum/Leptos server.
///
/// Uses current_thread runtime with LocalSet to provide the proper runtime context for Leptos.
/// This fixes the "spawn_local called from outside of a task::LocalSet" error.
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize path utilities first
    utils::init();

    // Create a current_thread runtime which is compatible with LocalSet
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()?;

    // Create a LocalSet and run everything within it
    let local = tokio::task::LocalSet::new();

    rt.block_on(local.run_until(async { run_server().await }))
}

/// Main server logic that runs within the LocalSet context.
///
/// This function contains all the server initialization and startup logic,
/// and must be run within a tokio::task::LocalSet for Leptos compatibility.
async fn run_server() -> Result<(), Box<dyn std::error::Error>> {
    // Load environment variables
    dotenvy::dotenv().ok();

    // Load configuration from TOML file with environment overrides
    let config = match Config::load() {
        Ok(config) => config,
        Err(e) => {
            eprintln!("Failed to load configuration: {}", e);
            std::process::exit(1);
        }
    };

    tracing::info!("Configuration loaded successfully");
    tracing::info!("Server: {}:{}", config.server.host, config.server.port);
    tracing::info!("Environment: {:?}", config.server.environment);
    tracing::info!("Protocol: {:?}", config.server.protocol);

    // Set up tracing subscriber with configured log level
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(&config.server.log_level)),
        )
        .init();

    std::panic::set_hook(Box::new(|info| {
        tracing::error!("PANIC: {}", info);
    }));

    // Load Leptos configuration
    let leptos_conf = match get_configuration(None) {
        Ok(conf) => conf,
        Err(e) => {
            tracing::error!("Failed to load Leptos configuration: {}", e);
            std::process::exit(1);
        }
    };

    // Override Leptos config with our configuration
    let mut leptos_options = leptos_conf.leptos_options;
    leptos_options.site_addr = config
        .server_address()
        .parse()
        .map_err(|e| format!("Invalid server address: {}", e))?;

    let leptos_options_for_routes = leptos_options.clone();
    let routes = generate_route_list(|| view! { <App /> });

    // Log the generated routes for debugging
    tracing::info!("Generated routes: {:?}", routes);

    // Since we're using custom routing, we need to add our custom routes manually
    // This is a workaround for the custom routing system
    // We'll use a different approach - set up specific route handlers for each custom route

    // For now, let's use the original routes and handle the custom routing differently
    let routes = routes;

    // Initialize security components based on configuration
    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()
    };

    // Initialize database connection (if needed)
    #[cfg(any(feature = "auth", feature = "content-db"))]
    let (database, pool, database_pool) = {
        let database_config = DatabaseConfig {
            url: config.database.url.clone(),
            max_connections: config.database.max_connections,
            min_connections: config.database.min_connections,
            connect_timeout: std::time::Duration::from_secs(config.database.connect_timeout),
            idle_timeout: std::time::Duration::from_secs(config.database.idle_timeout),
            max_lifetime: std::time::Duration::from_secs(config.database.max_lifetime),
        };

        tracing::info!("Connecting to database: {}", database_config.url);

        let database_pool = DatabasePool::new(&database_config).await.map_err(|e| {
            tracing::error!("Failed to connect to database: {}", e);
            std::process::exit(1);
        })?;

        let db_type = database_pool.database_type();
        tracing::info!("Database type detected: {:?}", db_type);

        let database = Database::new(database_pool.clone());

        // For backward compatibility with existing code that expects PgPool
        #[cfg(feature = "auth")]
        let pool = match &database_pool {
            DatabasePool::PostgreSQL(pg_pool) => pg_pool.clone(),
            DatabasePool::SQLite(_) => {
                tracing::info!("Using SQLite database with database-agnostic auth system");
                // Create a dummy PgPool for compatibility (will be replaced gradually)
                sqlx::postgres::PgPoolOptions::new()
                    .max_connections(1)
                    .connect("postgres://dummy:dummy@localhost/dummy")
                    .await
                    .unwrap_or_else(|_| {
                        tracing::warn!("Could not create dummy PostgreSQL pool for compatibility");
                        tracing::info!("Auth services will use database-agnostic implementation");
                        std::process::exit(0); // Exit gracefully for now
                    })
            }
        };

        #[cfg(not(feature = "auth"))]
        let pool = match &database_pool {
            DatabasePool::PostgreSQL(pg_pool) => pg_pool.clone(),
            DatabasePool::SQLite(_) => {
                // Create a dummy pool that won't be used
                sqlx::postgres::PgPoolOptions::new()
                    .max_connections(1)
                    .connect("postgres://dummy:dummy@localhost/dummy")
                    .await
                    .unwrap_or_else(|_| std::process::exit(1))
            }
        };

        (database, pool, database_pool)
    };

    // Initialize authentication services
    #[cfg(feature = "auth")]
    let (auth_service, auth_repository, jwt_service) = {
        // Use the new database-agnostic auth repository
        let auth_repository = Arc::new(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");
        (auth_service, auth_repository, jwt_service)
    };

    // Initialize content services
    #[cfg(feature = "content-db")]
    let content_service = {
        let content_repository = Arc::new(ContentRepository::from_pool(&database_pool));
        Arc::new(
            ContentService::new(content_repository)
                .with_source(ContentSource::Database)
                .with_cache(true),
        )
    };

    // Initialize email service
    #[cfg(feature = "email")]
    let email_service = {
        // Resolve email template directory relative to root path
        let email_template_dir = config
            .email
            .template_dir
            .as_ref()
            .map(|dir| config.get_absolute_path(dir))
            .unwrap_or_else(|| config.get_absolute_path("templates/email"));

        let email_service_builder = EmailServiceBuilder::new()
            .default_from(&config.email.from_email)
            .default_from_name(&config.email.from_name)
            .template_dir(&email_template_dir.unwrap_or_default())
            .enabled(config.email.enabled);

        // Configure provider based on config
        let email_service_builder = match config.email.provider.as_str() {
            "smtp" => {
                let smtp_config = crate::email::SmtpConfig {
                    host: config.email.smtp_host.clone(),
                    port: config.email.smtp_port,
                    username: config.email.smtp_username.clone(),
                    password: config.email.smtp_password.clone(),
                    use_tls: config.email.smtp_use_tls,
                    use_starttls: config.email.smtp_use_starttls,
                };
                email_service_builder.smtp_provider(smtp_config)
            }
            "sendgrid" => {
                let sendgrid_config = crate::email::SendGridConfig {
                    api_key: config.email.sendgrid_api_key.clone(),
                    endpoint: config.email.sendgrid_endpoint.clone(),
                };
                email_service_builder.sendgrid_provider(sendgrid_config)
            }
            _ => {
                // Default to console provider
                email_service_builder.console_provider()
            }
        };

        let email_service = email_service_builder.build().await.map_err(|e| {
            tracing::error!("Failed to initialize email service: {}", e);
            std::process::exit(1);
        })?;

        tracing::info!(
            "Email service initialized with provider: {}",
            email_service.provider_name()
        );
        tracing::info!("Email service enabled: {}", email_service.is_enabled());
        Arc::new(email_service)
    };

    // Initialize metrics service if enabled
    #[cfg(feature = "metrics")]
    let (metrics_registry, metrics_service) = if config.app.enable_metrics {
        let service = MetricsService::new().map_err(|e| {
            tracing::error!("Failed to create metrics service: {}", e);
            std::process::exit(1);
        })?;
        let registry = service.registry().cloned();

        (registry, Some(service))
    } else {
        (None, None)
    };

    // Create unified application state
    let app_state = AppState {
        leptos_options: leptos_options.clone(),
        csrf_state,
        rate_limiter,
        #[cfg(feature = "auth")]
        auth_service: auth_service.clone(),
        #[cfg(feature = "auth")]
        jwt_service: jwt_service.clone(),
        #[cfg(feature = "auth")]
        auth_repository: auth_repository.clone(),
        #[cfg(feature = "content-db")]
        content_service: content_service.clone(),
        #[cfg(feature = "email")]
        email_service: email_service.clone(),
        #[cfg(feature = "metrics")]
        metrics_registry,
    };

    // Start building the router with leptos routes first (they handle SSR properly)
    let mut app = Router::new()
        .leptos_routes(&app_state.leptos_options, routes, move || {
            shell(leptos_options_for_routes.clone())
        })
        // Add catch-all route for custom client-side routing
        .route(
            "/about",
            axum::routing::get({
                let opts = leptos_options.clone();
                move || {
                    let opts = opts.clone();
                    async move {
                        axum::response::Html(
                            shell_with_path(opts, Some("/about".to_string())).to_html(),
                        )
                    }
                }
            }),
        )
        .route(
            "/user",
            axum::routing::get({
                let opts = leptos_options.clone();
                move || {
                    let opts = opts.clone();
                    async move {
                        axum::response::Html(
                            shell_with_path(opts, Some("/user".to_string())).to_html(),
                        )
                    }
                }
            }),
        )
        .route(
            "/daisyui",
            axum::routing::get({
                let opts = leptos_options.clone();
                move || {
                    let opts = opts.clone();
                    async move {
                        axum::response::Html(
                            shell_with_path(opts, Some("/daisyui".to_string())).to_html(),
                        )
                    }
                }
            }),
        )
        .route(
            "/features-demo",
            axum::routing::get({
                let opts = leptos_options.clone();
                move || {
                    let opts = opts.clone();
                    async move {
                        axum::response::Html(
                            shell_with_path(opts, Some("/features-demo".to_string())).to_html(),
                        )
                    }
                }
            }),
        )
        .nest_service(
            "/pkg",
            ServeDir::new("target/site/pkg").append_index_html_on_directories(false),
        )
        .nest_service(
            "/public",
            ServeDir::new(&config.server_dirs.public_dir)
                .precompressed_gzip()
                .precompressed_br()
                .precompressed_deflate(),
        )
        .fallback(leptos_axum::file_and_error_handler(shell))
        .with_state(app_state.leptos_options.clone());

    // Create a router for additional routes that need their own state
    let api_router = Router::new();

    // Add auth routes if feature is enabled
    #[cfg(feature = "auth")]
    let api_router = {
        let auth_routes = create_auth_routes().with_state(auth_service.clone());
        api_router.nest("/auth", auth_routes)
    };

    // Add content routes if feature is enabled
    #[cfg(feature = "content-db")]
    let api_router = {
        let content_routes = create_content_routes().with_state(content_service.clone());
        api_router.nest("/content", content_routes)
    };

    // Add email routes if feature is enabled
    #[cfg(feature = "email")]
    let api_router = {
        let email_routes = create_email_routes().with_state(email_service.clone());
        api_router.nest("/email", email_routes)
    };

    // Add health check routes
    let health_routes = create_health_routes().with_state(app_state.clone());
    let api_router = api_router.merge(health_routes);

    // Add metrics routes if feature is enabled
    #[cfg(feature = "metrics")]
    let api_router = if config.app.enable_metrics {
        let metrics_routes = create_metrics_routes().with_state(app_state.clone());
        api_router.merge(metrics_routes)
    } else {
        api_router
    };

    // Merge the API router with the main app
    app = app.nest("/api", api_router);

    // Add metrics middleware if feature is enabled
    #[cfg(feature = "metrics")]
    let app = if config.app.enable_metrics {
        app.layer(axum::middleware::from_fn_with_state(
            app_state.clone(),
            metrics_middleware,
        ))
    } else {
        app
    };

    // Add auth middleware if feature is enabled
    #[cfg(feature = "auth")]
    let app = {
        app.layer(CookieManagerLayer::new())
            .layer(axum::middleware::from_fn_with_state(
                (jwt_service.clone(), auth_repository.clone()),
                auth_middleware,
            ))
    };

    // Add security headers
    let app = app.layer(axum::middleware::from_fn({
        let config = security_headers_config.clone();
        move |req: Request, next: Next| {
            let config = config.clone();
            async move {
                let response = next.run(req).await;
                add_security_headers_with_config(response, &config)
            }
        }
    }));

    // Add development cache headers
    let app = app.layer(middleware::from_fn(dev_cache_middleware));

    let addr = config.server_address();
    tracing::info!("Server starting on {}", addr);
    tracing::info!("Environment: {:?}", config.server.environment);
    tracing::info!("Log level: {}", config.server.log_level);
    tracing::info!("Security features enabled: CSRF, Rate Limiting, Security Headers");
    tracing::info!("Application: {} v{}", config.app.name, config.app.version);
    #[cfg(any(feature = "auth", feature = "content-db"))]
    tracing::info!("Database URL: {}", config.database.url);
    tracing::info!("Server directories:");
    tracing::info!("  Public: {}", config.server_dirs.public_dir);
    tracing::info!("  Uploads: {}", config.server_dirs.uploads_dir);
    tracing::info!("  Logs: {}", config.server_dirs.logs_dir);
    tracing::info!("  Cache: {}", config.server_dirs.cache_dir);

    // Health check endpoints
    tracing::info!("Health check endpoints available:");
    tracing::info!("  /health - Comprehensive health check");
    tracing::info!("  /health/live - Liveness probe");
    tracing::info!("  /health/ready - Readiness probe");

    // Metrics endpoints
    #[cfg(feature = "metrics")]
    if config.app.enable_metrics {
        tracing::info!("Metrics collection enabled");
        tracing::info!("Metrics endpoints available:");
        tracing::info!("  /metrics - Prometheus metrics");
        tracing::info!("  /metrics/health - Health metrics (JSON)");
    }

    #[cfg(feature = "auth")]
    {
        tracing::info!("Authentication endpoints available at: /api/auth/*");
        tracing::info!(
            "OAuth providers configured: {:?}",
            auth_service.get_oauth_providers()
        );
    }

    #[cfg(feature = "content-db")]
    {
        tracing::info!("Content management endpoints available at: /api/content/*");
    }

    #[cfg(feature = "email")]
    {
        tracing::info!(
            "Email service configured with provider: {}",
            email_service.provider_name()
        );
        tracing::info!("Email sending enabled: {}", email_service.is_enabled());
    }

    #[cfg(not(feature = "auth"))]
    {
        tracing::info!("Authentication disabled - no auth endpoints available");
    }

    #[cfg(not(feature = "content-db"))]
    {
        tracing::info!("Database content disabled - using static content only");
    }

    #[cfg(not(feature = "email"))]
    {
        tracing::info!("Email service disabled - no email functionality available");
    }

    match config.server.protocol {
        Protocol::Http => {
            let listener = tokio::net::TcpListener::bind(&addr).await.map_err(|e| {
                tracing::error!("Failed to bind to address {}: {}", addr, e);
                std::process::exit(1);
            })?;
            tracing::info!("Listening on http://{}", &addr);
            if let Err(e) = axum::serve(listener, app).await {
                tracing::error!("Server failed: {}", e);
                std::process::exit(1);
            }
        }
        Protocol::Https => {
            #[cfg(feature = "tls")]
            {
                let tls_config = config
                    .server
                    .tls
                    .as_ref()
                    .ok_or("TLS configuration is required for HTTPS but not provided")?;
                let rustls_config =
                    match config::create_tls_config(&tls_config.cert_path, &tls_config.key_path)
                        .await
                    {
                        Ok(config) => config,
                        Err(e) => {
                            tracing::error!("Failed to create TLS config: {}", e);
                            std::process::exit(1);
                        }
                    };

                tracing::info!("Listening on https://{}", &addr);
                tracing::info!("TLS certificate: {}", tls_config.cert_path.display());
                tracing::info!("TLS private key: {}", tls_config.key_path.display());

                let socket_addr = addr
                    .parse()
                    .map_err(|e| format!("Invalid socket address '{}': {}", addr, e))?;
                if let Err(e) = axum_server::bind_rustls(socket_addr, rustls_config)
                    .serve(app.into_make_service())
                    .await
                {
                    tracing::error!("HTTPS server failed: {}", e);
                    std::process::exit(1);
                }
            }
            #[cfg(not(feature = "tls"))]
            {
                tracing::error!("HTTPS protocol requested but TLS feature is not enabled");
                tracing::error!("Please enable the 'tls' feature or use HTTP protocol");
                std::process::exit(1);
            }
        }
    }

    Ok(())
}
