use std::sync::Arc;

use crate::core::config::Settings;
use crate::services::{
    get_service_pid, is_systemd_service_running, run_sudo_command, write_with_sudo_tee,
    ServiceStatus,
};
use log::info;
use std::path::PathBuf;

pub struct HttpService {
    pub(crate) settings: Arc<Settings>,
}

impl HttpService {
    #[expect(dead_code, reason = "Constructed directly by ServiceManager::new, not by external callers")]
    pub fn new(settings: Settings) -> Self {
        Self { settings: Arc::new(settings) }
    }

    pub async fn generate_config(&self) -> anyhow::Result<()> {
        let root_dir = &self.settings.http.root_dir;

        // Generate Apache2 configuration for serving boot files
        let apache_config = format!(
            r#"# Generated by diskless-boot-server
# Apache2 configuration for PXE boot file serving

<VirtualHost {server_ip}:{port}>
    ServerName {hostname}
    DocumentRoot {root_dir}

    <Directory {root_dir}>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted

        # Enable directory listing for easier debugging
        Options +Indexes
        IndexOptions FancyIndexing
    </Directory>
    # Logging
    ErrorLog ${{APACHE_LOG_DIR}}/pxe-error.log
    CustomLog ${{APACHE_LOG_DIR}}/pxe-access.log combined
</VirtualHost>
"#,
            server_ip = self.settings.http.server_ip,
            port = self.settings.http.port,
            hostname = self.settings.server.hostname,
            root_dir = root_dir.to_string(),
        );

        // Write Apache2 site configuration
        let config_path = PathBuf::from("/etc/apache2/sites-available/diskless-server.conf");

        // Ensure parent directory exists
        if let Some(parent) = config_path.parent() {
            std::fs::create_dir_all(parent)
                .map_err(|e| anyhow::anyhow!("Failed to create parent directory: {}", e))?;
        }

        write_with_sudo_tee(
            "/etc/apache2/sites-available/diskless-server.conf",
            &apache_config,
        )
        .await?;

        info!("Apache2 configuration written to {}", config_path.display());

        // Enable the site
        run_sudo_command(["a2ensite", "diskless-server"]).await?;

        // Enable required modules
        run_sudo_command(["a2enmod", "headers"]).await?;

        info!("Apache2 site enabled");
        Ok(())
    }

    pub async fn start(&self) -> anyhow::Result<()> {
        // Generate config first
        self.generate_config().await?;

        // Start Apache2
        run_sudo_command(["systemctl", "start", "apache2"]).await?;

        info!("Apache2 service started");
        Ok(())
    }

    pub async fn stop(&self) -> anyhow::Result<()> {
        run_sudo_command(["systemctl", "stop", "apache2"]).await?;

        info!("Apache2 service stopped");
        Ok(())
    }

    pub async fn reload(&self) -> anyhow::Result<()> {
        // Regenerate config
        self.generate_config().await?;

        // Reload Apache2
        run_sudo_command(["systemctl", "reload", "apache2"]).await?;

        info!("Apache2 service reloaded");
        Ok(())
    }

    pub async fn get_config(&self) -> anyhow::Result<String> {
        let config_path = PathBuf::from("/etc/apache2/sites-available/diskless-server.conf");
        if config_path.exists() {
            let content = std::fs::read_to_string(&config_path)?;
            Ok(content)
        } else {
            // Return default configuration if file doesn't exist
            let root_dir = &self.settings.tftp.root_dir;
            let apache_config = format!(
                r#"# Generated by diskless-boot-server
# Apache2 configuration for PXE boot file serving

<VirtualHost *:8080>
    ServerName {hostname}
    DocumentRoot {root_dir}

    <Directory {root_dir}>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted

        # Enable directory listing for easier debugging
        Options +Indexes
        IndexOptions FancyIndexing
    </Directory>

    # Serve iPXE scripts
    <Location /boot.ipxe>
        Header set Content-Type "text/plain"
    </Location>

    # Logging
    ErrorLog ${{APACHE_LOG_DIR}}/pxe-error.log
    CustomLog ${{APACHE_LOG_DIR}}/pxe-access.log combined
</VirtualHost>

# Listen on port 8080
Listen 8080
"#,
                hostname = self.settings.server.hostname,
                root_dir = root_dir.to_string(),
            );
            Ok(apache_config)
        }
    }

    pub async fn status(&self) -> anyhow::Result<ServiceStatus> {
        let running = is_systemd_service_running("apache2").await?;
        let pid = if running {
            get_service_pid("apache2").await?
        } else {
            None
        };

        Ok(ServiceStatus {
            running,
            pid,
            message: if running {
                "Apache2 HTTP server is running on port 8080".to_string()
            } else {
                "Apache2 HTTP server is not running".to_string()
            },
        })
    }
}
