use std::error::Error;
use std::path::PathBuf;
use std::process::Command;
use log::{error, info};
use crate::service::codegen::ServiceFileGenerator;
use crate::service::codegen::systemd::SystemDServiceFileGenerator;
use crate::service::ServiceManager;

pub struct SystemDServiceManager {}
impl ServiceManager for SystemDServiceManager {
    fn install(&self, bin_path: PathBuf, name: &str, server_url: &str) -> Result<(), Box<dyn Error>> {
        info!("Installing for SystemD");

        SystemDServiceFileGenerator::create_service_files(bin_path, name, server_url)?;

        info!("Enabling the SystemD service");

        let out = Command::new("systemctl").args(["enable", &SystemDServiceFileGenerator::get_service_file_name(name)]).output()?;
        if !out.status.success() {
            error!("Error enabling the SystemD service (command exited with non-zero exit code)");
            error!("stdout:");
            error!("{}", String::from_utf8(out.stdout)?);
            error!("stderr:");
            error!("{}", String::from_utf8(out.stderr)?);
            return Err("Command exited with non-zero exit code".into());
        }

        info!("Installation successful");

        Ok(())
    }

    fn uninstall(&self, name: &str) -> Result<(), Box<dyn Error>> {
        info!("Uninstalling SystemD service files");

        info!("Disabling the SystemD service");

        let out = Command::new("systemctl").args(["disable", &SystemDServiceFileGenerator::get_service_file_name(name)]).output()?;
        if !out.status.success() {
            error!("Error disabling the SystemD service (command exited with non-zero exit code)");
            error!("stdout:");
            error!("{}", String::from_utf8(out.stdout)?);
            error!("stderr:");
            error!("{}", String::from_utf8(out.stderr)?);
            return Err("Command exited with non-zero exit code".into());
        }

        info!("Removing the service files");

        SystemDServiceFileGenerator::delete_service_files(name)?;

        Ok(())
    }

    fn start(&self, name: &str) -> Result<(), Box<dyn Error>> {
        info!("Starting the SystemD service");

        let out = Command::new("systemctl").args(["start", &SystemDServiceFileGenerator::get_service_file_name(name)]).output()?;
        if !out.status.success() {
            error!("Error starting the SystemD service (command exited with non-zero exit code)");
            error!("stdout:");
            error!("{}", String::from_utf8(out.stdout)?);
            error!("stderr:");
            error!("{}", String::from_utf8(out.stderr)?);
            return Err("Command exited with non-zero exit code".into());
        }

        Ok(())
    }

    fn stop(&self, name: &str) -> Result<(), Box<dyn Error>> {
        info!("Stopping the SystemD service");

        let out = Command::new("systemctl").args(["stop", &SystemDServiceFileGenerator::get_service_file_name(name)]).output()?;
        if !out.status.success() {
            error!("Error stopping the SystemD service (command exited with non-zero exit code)");
            error!("stdout:");
            error!("{}", String::from_utf8(out.stdout)?);
            error!("stderr:");
            error!("{}", String::from_utf8(out.stderr)?);
            return Err("Command exited with non-zero exit code".into());
        }

        Ok(())
    }
}