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 SambaService {
    pub(crate) settings: Arc<Settings>,
}

impl SambaService {
    #[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 start(&self) -> anyhow::Result<()> {
        // Create share directory if it doesn't exist using elevated privileges
        let share_path = &self.settings.samba.share_path;
        let share_path_str = share_path.to_string_lossy();
        run_sudo_command(["mkdir", "-p", &share_path_str]).await?;

        // Generate and write Samba configuration
        self.generate_config().await?;

        // Start Samba services
        run_sudo_command(["systemctl", "start", "smbd"]).await?;
        run_sudo_command(["systemctl", "start", "nmbd"]).await?;

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

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

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

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

        run_sudo_command(["systemctl", "restart", "smbd"]).await?;

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

    pub async fn status(&self) -> anyhow::Result<ServiceStatus> {
        let smbd_running = is_systemd_service_running("smbd").await?;
        let nmbd_running = is_systemd_service_running("nmbd").await?;
        let running = smbd_running && nmbd_running;

        let pid = if running {
            get_service_pid("smbd").await?
        } else {
            None
        };

        Ok(ServiceStatus {
            running,
            pid,
            message: if running {
                "Samba server is running (smbd + nmbd)".to_string()
            } else if smbd_running {
                "Only smbd is running".to_string()
            } else if nmbd_running {
                "Only nmbd is running".to_string()
            } else {
                "Samba server is not running".to_string()
            },
        })
    }

    pub async fn get_config(&self) -> anyhow::Result<String> {
        let config_path = PathBuf::from("/etc/samba/smb.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 config = &self.settings.samba;

            let smb_conf = format!(
                r#"# Generated by diskless-boot-server
# Do not edit manually

[global]
   workgroup = {}
   server string = Diskless Boot Server
   netbios name = {}
   security = user
   map to guest = Bad User
   dns proxy = no

   # Logging
   log file = /var/log/samba/log.%m
   max log size = 1000
   logging = file

[{}]
   path = {}
   browseable = yes
   writable = {}
   guest ok = {}
   read only = {}
   create mask = 0755
   directory mask = 0755
   force user = nobody
   force group = nogroup
"#,
                config.workgroup,
                self.settings.server.hostname,
                config.share_name,
                config.share_path.display(),
                if config.read_only { "no" } else { "yes" },
                if config.guest_ok { "yes" } else { "no" },
                if config.read_only { "yes" } else { "no" },
            );
            Ok(smb_conf)
        }
    }

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

        let smb_conf = format!(
            r#"# Generated by diskless-boot-server
# Do not edit manually

[global]
   workgroup = {}
   server string = Diskless Boot Server
   netbios name = {}
   security = user
   map to guest = Bad User
   dns proxy = no

   # Logging
   log file = /var/log/samba/log.%m
   max log size = 1000
   logging = file

[{}]
   path = {}
   browseable = yes
   writable = {}
   guest ok = {}
   read only = {}
   create mask = 0755
   directory mask = 0755
   force user = nobody
   force group = nogroup
"#,
            config.workgroup,
            self.settings.server.hostname,
            config.share_name,
            config.share_path.display(),
            if config.read_only { "no" } else { "yes" },
            if config.guest_ok { "yes" } else { "no" },
            if config.read_only { "yes" } else { "no" },
        );

        write_with_sudo_tee("/etc/samba/smb.conf", &smb_conf).await?;

        info!("Samba configuration written to /etc/samba/smb.conf");
        Ok(())
    }
}
