//! DBus interface implementation for apt-ostree daemon
//! Following the rpm-ostree DBus interface specification

use zbus::{dbus_interface, fdo};
use crate::daemon::{
    DaemonConfig, DaemonResult, DaemonError,
    TransactionManager, TransactionType, TransactionState,
    OstreeManager, AptManager, SecurityManager, SysrootManager, OsManager,
};
use std::sync::Arc;
use tokio::sync::RwLock;
use std::collections::HashMap;
use serde::{Serialize, Deserialize};

/// DBus interface for apt-ostree daemon
pub struct DaemonDBus {
    config: DaemonConfig,
    transaction_manager: Arc<RwLock<TransactionManager>>,
    ostree_manager: Arc<RwLock<OstreeManager>>,
    apt_manager: Arc<RwLock<AptManager>>,
    security_manager: Arc<RwLock<SecurityManager>>,
    sysroot_manager: Arc<RwLock<SysrootManager>>,
    os_manager: Arc<RwLock<OsManager>>,
    clients: Arc<tokio::sync::Mutex<HashMap<String, ClientInfo>>>,
}

impl DaemonDBus {
    pub fn new(config: DaemonConfig) -> DaemonResult<Self> {
        let transaction_manager = Arc::new(RwLock::new(TransactionManager::new()));
        let ostree_manager = Arc::new(RwLock::new(OstreeManager::new(&config.ostree_sysroot)?));
        let apt_manager = Arc::new(RwLock::new(AptManager::new(&config.apt_cache_dir)?));
        let security_manager = Arc::new(RwLock::new(SecurityManager::new()));
        let sysroot_manager = Arc::new(RwLock::new(SysrootManager::new(&config.ostree_sysroot)?));
        let os_manager = Arc::new(RwLock::new(OsManager::new()?));

        Ok(Self {
            config,
            transaction_manager,
            ostree_manager,
            apt_manager,
            security_manager,
            sysroot_manager,
            os_manager,
            clients: Arc::new(tokio::sync::Mutex::new(HashMap::new())),
        })
    }
}

/// Deployment metadata structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentMetadata {
    pub id: String,
    pub commit: String,
    pub timestamp: String,
    pub origin: String,
    pub booted: bool,
    pub staged: bool,
    pub pending: bool,
    pub rollback: bool,
}

/// Transaction options structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransactionOptions {
    pub reboot: Option<bool>,
    pub allow_downgrade: Option<bool>,
    pub dry_run: Option<bool>,
    pub lock_finalization: Option<bool>,
}

/// Client information structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientInfo {
    pub id: String,
    pub description: String,
    pub registered_at: chrono::DateTime<chrono::Utc>,
    pub last_activity: chrono::DateTime<chrono::Utc>,
    pub active_transactions: Vec<String>,
}

/// Sysroot Interface - Root interface for system operations
#[dbus_interface(name = "org.projectatomic.aptostree1.Sysroot")]
impl DaemonDBus {
    /// Get currently booted OS object path
    #[dbus_interface(property)]
    async fn booted(&self) -> fdo::Result<String> {
        // TODO: Implement real booted OS detection
        Ok("/org/projectatomic/aptostree1/OS/default".to_string())
    }

    /// Get system root path
    #[dbus_interface(property)]
    async fn path(&self) -> fdo::Result<String> {
        Ok("/".to_string())
    }

    /// Get active transaction information
    #[dbus_interface(property)]
    async fn active_transaction(&self) -> fdo::Result<(String, String, String)> {
        // TODO: Implement real active transaction tracking
        Ok(("none".to_string(), "none".to_string(), "none".to_string()))
    }

    /// Get active transaction path
    #[dbus_interface(property)]
    async fn active_transaction_path(&self) -> fdo::Result<String> {
        // TODO: Implement real active transaction path
        Ok("/".to_string())
    }

    /// Get all deployments
    #[dbus_interface(property)]
    async fn deployments(&self) -> fdo::Result<Vec<HashMap<String, zbus::zvariant::Value>>> {
        // TODO: Implement real deployment listing
        let mut deployments = Vec::new();
        let mut deployment = HashMap::new();
        deployment.insert("id".to_string(), zbus::zvariant::Value::Str("default".to_string()));
        deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
        deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(true));
        deployments.push(deployment);
        Ok(deployments)
    }

    /// Get automatic update policy
    #[dbus_interface(property)]
    async fn automatic_update_policy(&self) -> fdo::Result<String> {
        Ok("none".to_string())
    }

    /// Register a client
    async fn register_client(&self, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<()> {
        tracing::info!("Client registered with options: {:?}", options);
        
        // Extract client information from options
        let client_id = options.get("client_id")
            .and_then(|v| v.downcast_ref::<String>())
            .cloned()
            .unwrap_or_else(|| format!("client_{}", chrono::Utc::now().timestamp()));
        
        let description = options.get("description")
            .and_then(|v| v.downcast_ref::<String>())
            .cloned()
            .unwrap_or_else(|| "Unknown client".to_string());
        
        // Store client information
        let mut clients = self.clients.lock().await;
        clients.insert(client_id.clone(), ClientInfo {
            id: client_id,
            description,
            registered_at: chrono::Utc::now(),
            last_activity: chrono::Utc::now(),
            active_transactions: Vec::new(),
        });
        
        tracing::info!("Client registered successfully");
        Ok(())
    }

    /// Unregister a client
    async fn unregister_client(&self, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<()> {
        tracing::info!("Client unregistered with options: {:?}", options);
        
        let client_id = options.get("client_id")
            .and_then(|v| v.downcast_ref::<String>())
            .cloned()
            .unwrap_or_else(|| format!("client_{}", chrono::Utc::now().timestamp()));
        
        let mut clients = self.clients.lock().await;
        if let Some(client_info) = clients.remove(&client_id) {
            // Cancel any active transactions for this client
            if !client_info.active_transactions.is_empty() {
                tracing::info!("Cancelling {} active transactions for client {}", 
                    client_info.active_transactions.len(), client_id);
                // In a real implementation, we would cancel these transactions
            }
            tracing::info!("Client unregistered successfully");
        } else {
            tracing::warn!("Client {} not found for unregistration", client_id);
        }
        
        Ok(())
    }

    /// Reload sysroot
    async fn reload(&self) -> fdo::Result<()> {
        tracing::info!("Reloading sysroot");
        
        // Reload OSTree sysroot information
        let mut ostree_manager = self.ostree_manager.write().await;
        if let Err(e) = ostree_manager.reload_sysroot() {
            tracing::error!("Failed to reload OSTree sysroot: {}", e);
            return Err(fdo::Error::Failed("Failed to reload OSTree sysroot".to_string()));
        }
        
        // Reload sysroot manager
        let mut sysroot_manager = self.sysroot_manager.write().await;
        if let Err(e) = sysroot_manager.reload() {
            tracing::error!("Failed to reload sysroot manager: {}", e);
            return Err(fdo::Error::Failed("Failed to reload sysroot manager".to_string()));
        }
        
        tracing::info!("Sysroot reloaded successfully");
        Ok(())
    }

    /// Reload configuration
    async fn reload_config(&self) -> fdo::Result<()> {
        tracing::info!("Reloading configuration");
        
        // Reload APT configuration
        let mut apt_manager = self.apt_manager.write().await;
        if let Err(e) = apt_manager.reload_config() {
            tracing::error!("Failed to reload APT configuration: {}", e);
            return Err(fdo::Error::Failed("Failed to reload APT configuration".to_string()));
        }
        
        // Reload security configuration
        let mut security_manager = self.security_manager.write().await;
        if let Err(e) = security_manager.reload_config() {
            tracing::error!("Failed to reload security configuration: {}", e);
            return Err(fdo::Error::Failed("Failed to reload security configuration".to_string()));
        }
        
        tracing::info!("Configuration reloaded successfully");
        Ok(())
    }

    /// Get OS object by name
    async fn get_os(&self, name: String) -> fdo::Result<String> {
        tracing::info!("Getting OS object for name: {}", name);
        
        // Check if the OS name exists in our system
        let os_manager = self.os_manager.read().await;
        if let Ok(os_info) = os_manager.get_os_info(&name) {
            let os_path = format!("/org/projectatomic/aptostree1/OS/{}", name);
            tracing::info!("OS object found: {}", os_path);
            Ok(os_path)
        } else {
            // Fallback to default OS path
            let default_path = "/org/projectatomic/aptostree1/OS/default".to_string();
            tracing::warn!("OS '{}' not found, returning default: {}", name, default_path);
            Ok(default_path)
        }
    }
}

/// OS Interface - Operating system operations
#[dbus_interface(name = "org.projectatomic.aptostree1.OS")]
impl DaemonDBus {
    /// Get booted deployment
    #[dbus_interface(property)]
    async fn booted_deployment(&self) -> fdo::Result<HashMap<String, zbus::zvariant::Value>> {
        let mut deployment = HashMap::new();
        
        // Try to get real OSTree deployment information
        match std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    // Parse ostree admin status output
                    if let Some(booted_line) = output_str.lines().find(|line| line.contains("*")) {
                        // Extract deployment ID and commit from line like "* debian 1234567.0 (1234567)"
                        let parts: Vec<&str> = booted_line.split_whitespace().collect();
                        if parts.len() >= 3 {
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str(parts[1].to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str(parts[2].to_string()));
                            deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(true));
                        } else {
                            // Fallback to parsed values
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str("debian".to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                            deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(true));
                        }
                    } else {
                        // No booted deployment found
                        deployment.insert("id".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                        deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                        deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(false));
                    }
                } else {
                    // Command failed, use fallback
                    deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                    deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                    deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(false));
                }
            }
            Err(_) => {
                // Command not found or failed, use fallback
                deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                deployment.insert("booted".to_string(), zbus::zvariant::Value::Bool(false));
            }
        }
        
        Ok(deployment)
    }

    /// Get default deployment
    #[dbus_interface(property)]
    async fn default_deployment(&self) -> fdo::Result<HashMap<String, zbus::zvariant::Value>> {
        let mut deployment = HashMap::new();
        
        // Try to get real OSTree default deployment information
        match std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    // Parse ostree admin status output to find default deployment
                    if let Some(default_line) = output_str.lines().find(|line| line.contains("(default)")) {
                        // Extract deployment ID and commit from line like "debian 1234567.0 (default)"
                        let parts: Vec<&str> = default_line.split_whitespace().collect();
                        if parts.len() >= 2 {
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str(parts[0].to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str(parts[1].to_string()));
                        } else {
                            // Fallback to parsed values
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str("debian".to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                        }
                    } else {
                        // No default deployment found, use first deployment
                        if let Some(first_line) = output_str.lines().next() {
                            let parts: Vec<&str> = first_line.split_whitespace().collect();
                            if parts.len() >= 2 {
                                deployment.insert("id".to_string(), zbus::zvariant::Value::Str(parts[0].to_string()));
                                deployment.insert("commit".to_string(), zbus::zvariant::Value::Str(parts[1].to_string()));
                            } else {
                                // Fallback to parsed values
                                deployment.insert("id".to_string(), zbus::zvariant::Value::Str("debian".to_string()));
                                deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                            }
                        } else {
                            // No deployments found
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                        }
                    }
                } else {
                    // Command failed, use fallback
                    deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                    deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                }
            }
            Err(_) => {
                // Command not found or failed, use fallback
                deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
            }
        }
        
        Ok(deployment)
    }

    /// Get rollback deployment
    #[dbus_interface(property)]
    async fn rollback_deployment(&self) -> fdo::Result<HashMap<String, zbus::zvariant::Value>> {
        let mut deployment = HashMap::new();
        
        // Try to get real OSTree rollback deployment information
        match std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    // Parse ostree admin status output to find rollback deployment
                    if let Some(rollback_line) = output_str.lines().find(|line| line.contains("rollback")) {
                        // Extract deployment ID and commit from rollback line
                        let parts: Vec<&str> = rollback_line.split_whitespace().collect();
                        if parts.len() >= 2 {
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str(parts[0].to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str(parts[1].to_string()));
                            deployment.insert("rollback".to_string(), zbus::zvariant::Value::Bool(true));
                        } else {
                            // Fallback to parsed values
                            deployment.insert("id".to_string(), zbus::zvariant::Value::Str("debian".to_string()));
                            deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                            deployment.insert("rollback".to_string(), zbus::zvariant::Value::Bool(true));
                        }
                    } else {
                        // No rollback deployment found
                        deployment.insert("id".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                        deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("none".to_string()));
                        deployment.insert("rollback".to_string(), zbus::zvariant::Value::Bool(false));
                    }
                } else {
                    // Command failed, use fallback
                    deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                    deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                    deployment.insert("rollback".to_string(), zbus::zvariant::Value::Bool(false));
                }
            }
            Err(_) => {
                // Command not found or failed, use fallback
                deployment.insert("id".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                deployment.insert("commit".to_string(), zbus::zvariant::Value::Str("unknown".to_string()));
                deployment.insert("rollback".to_string(), zbus::zvariant::Value::Bool(false));
            }
        }
        
        Ok(deployment)
    }

    /// Get cached update information
    #[dbus_interface(property)]
    async fn cached_update(&self) -> fdo::Result<HashMap<String, zbus::zvariant::Value>> {
        let mut update_info = HashMap::new();
        
        // Check for available updates using apt list --upgradable
        match std::process::Command::new("apt")
            .arg("list")
            .arg("--upgradable")
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    let upgradable_packages: Vec<&str> = output_str.lines()
                        .filter(|line| !line.starts_with("WARNING") && !line.is_empty())
                        .collect();
                    
                    if !upgradable_packages.is_empty() {
                        update_info.insert("available".to_string(), zbus::zvariant::Value::Bool(true));
                        update_info.insert("package_count".to_string(), zbus::zvariant::Value::U32(upgradable_packages.len() as u32));
                        
                        // Get the first few package names as examples
                        let package_names: Vec<String> = upgradable_packages.iter()
                            .take(5)
                            .map(|line| {
                                line.split('/').next().unwrap_or("unknown").to_string()
                            })
                            .collect();
                        update_info.insert("packages".to_string(), zbus::zvariant::Value::Array(
                            zbus::zvariant::Array::from(package_names.iter().map(|p| zbus::zvariant::Value::Str(p.clone())).collect::<Vec<_>>())
                        ));
                        
                        // Check if there are security updates
                        let security_updates: Vec<&str> = upgradable_packages.iter()
                            .filter(|line| line.contains("security"))
                            .collect();
                        update_info.insert("security_updates".to_string(), zbus::zvariant::Value::U32(security_updates.len() as u32));
                    } else {
                        update_info.insert("available".to_string(), zbus::zvariant::Value::Bool(false));
                        update_info.insert("package_count".to_string(), zbus::zvariant::Value::U32(0));
                        update_info.insert("packages".to_string(), zbus::zvariant::Value::Array(
                            zbus::zvariant::Array::new(zbus::zvariant::Signature::from_str_unchecked("s"))
                        ));
                        update_info.insert("security_updates".to_string(), zbus::zvariant::Value::U32(0));
                    }
                } else {
                    // Command failed, use fallback
                    update_info.insert("available".to_string(), zbus::zvariant::Value::Bool(false));
                    update_info.insert("package_count".to_string(), zbus::zvariant::Value::U32(0));
                    update_info.insert("packages".to_string(), zbus::zvariant::Value::Array(
                        zbus::zvariant::Array::new(zbus::zvariant::Signature::from_str_unchecked("s"))
                    ));
                    update_info.insert("security_updates".to_string(), zbus::zvariant::Value::U32(0));
                }
            }
            Err(_) => {
                // Command not found or failed, use fallback
                update_info.insert("available".to_string(), zbus::zvariant::Value::Bool(false));
                update_info.insert("package_count".to_string(), zbus::zvariant::Value::U32(0));
                update_info.insert("packages".to_string(), zbus::zvariant::Value::Array(
                    zbus::zvariant::Array::new(zbus::zvariant::Signature::from_str_unchecked("s"))
                ));
                update_info.insert("security_updates".to_string(), zbus::zvariant::Value::U32(0));
            }
        }
        
        Ok(update_info)
    }

    /// Check if cached update has RPM diff
    #[dbus_interface(property)]
    async fn has_cached_update_rpm_diff(&self) -> fdo::Result<bool> {
        // For Debian systems, we check for package differences rather than RPM diffs
        // Check if there are packages with different versions available
        
        match std::process::Command::new("apt")
            .arg("list")
            .arg("--upgradable")
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    let upgradable_packages: Vec<&str> = output_str.lines()
                        .filter(|line| !line.starts_with("WARNING") && !line.is_empty())
                        .collect();
                    
                    // Check if any packages have version differences
                    for package_line in upgradable_packages {
                        if package_line.contains(" [") && package_line.contains("]") {
                            // Extract current and available versions
                            if let Some(version_part) = package_line.split('[').nth(1) {
                                if let Some(available_version) = version_part.split(']').next() {
                                    // Check if this differs from installed version
                                    if let Some(package_name) = package_line.split('/').next() {
                                        let dpkg_output = std::process::Command::new("dpkg")
                                            .arg("-s")
                                            .arg(package_name)
                                            .output();
                                        
                                        if let Ok(dpkg_result) = dpkg_output {
                                            if dpkg_result.status.success() {
                                                let dpkg_str = String::from_utf8_lossy(&dpkg_result.stdout);
                                                if let Some(installed_line) = dpkg_str.lines().find(|line| line.starts_with("Version: ")) {
                                                    let installed_version = &installed_line[9..];
                                                    if installed_version != available_version {
                                                        tracing::info!("Package {} has version difference: {} -> {}", 
                                                            package_name, installed_version, available_version);
                                                        return Ok(true);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            Err(e) => {
                tracing::warn!("Failed to check for package updates: {}", e);
            }
        }
        
        Ok(false)
    }

    /// Get OS name
    #[dbus_interface(property)]
    async fn name(&self) -> fdo::Result<String> {
        Ok("default".to_string())
    }

    /// Deploy a specific revision
    async fn deploy(&self, revision: String, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Deploying revision: {} with options: {:?}", revision, options);
        
        // Generate transaction ID
        let transaction_id = format!("deploy_{}", chrono::Utc::now().timestamp());
        
        // Check if we're in an OSTree system
        let ostree_status = std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output();
        
        match ostree_status {
            Ok(output) => {
                if output.status.success() {
                    // Get current deployment info
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    let current_deployment = output_str.lines()
                        .find(|line| line.contains("*"))
                        .and_then(|line| {
                            let parts: Vec<&str> = line.split_whitespace().collect();
                            if parts.len() >= 2 {
                                Some((parts[1], parts[2]))
                            } else {
                                None
                            }
                        });
                    
                    if let Some((current_os, _current_commit)) = current_deployment {
                        tracing::info!("Deploying to OS: {}", current_os);
                        
                        // Parse revision (could be a commit hash or refspec)
                        let (remote, branch) = if revision.contains(':') {
                            let parts: Vec<&str> = revision.splitn(2, ':').collect();
                            (parts[0], parts[1])
                        } else {
                            ("origin", revision.as_str())
                        };
                        
                        // Execute deployment using ostree admin deploy
                        let mut deploy_command = std::process::Command::new("ostree");
                        deploy_command.arg("admin")
                            .arg("deploy")
                            .arg("--os")
                            .arg(current_os)
                            .arg(&format!("{}:{}", remote, branch));
                        
                        // Add options
                        if let Some(dry_run) = options.get("dry_run") {
                            if let Ok(dry_run_bool) = dry_run.downcast_ref::<bool>() {
                                if *dry_run_bool {
                                    deploy_command.arg("--dry-run");
                                }
                            }
                        }
                        
                        if let Some(force) = options.get("force") {
                            if let Ok(force_bool) = force.downcast_ref::<bool>() {
                                if *force_bool {
                                    deploy_command.arg("--force");
                                }
                            }
                        }
                        
                        let deploy_output = deploy_command.output();
                        
                        match deploy_output {
                            Ok(output) => {
                                if output.status.success() {
                                    tracing::info!("Deployment completed successfully");
                                    
                                    // Check if reboot is requested
                                    if let Some(reboot) = options.get("reboot") {
                                        if let Ok(reboot_bool) = reboot.downcast_ref::<bool>() {
                                            if *reboot_bool {
                                                tracing::info!("Reboot requested after deployment");
                                                // In a real implementation, this would trigger a reboot
                                            }
                                        }
                                    }
                                } else {
                                    let stderr = String::from_utf8_lossy(&output.stderr);
                                    tracing::error!("Deployment failed: {}", stderr);
                                }
                            }
                            Err(e) => {
                                tracing::error!("Failed to execute deployment: {}", e);
                            }
                        }
                    } else {
                        tracing::error!("Could not determine current deployment");
                    }
                } else {
                    tracing::error!("Failed to get OSTree status");
                }
            }
            Err(e) => {
                tracing::error!("OSTree not available: {}", e);
            }
        }
        
        Ok(transaction_id)
    }

    /// Upgrade the system
    async fn upgrade(&self, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Upgrading system with options: {:?}", options);
        
        // Generate transaction ID
        let transaction_id = format!("upgrade_{}", chrono::Utc::now().timestamp());
        
        // Build apt upgrade command
        let mut command = std::process::Command::new("apt");
        command.arg("upgrade");
        
        // Add options
        if let Some(dry_run) = options.get("dry_run") {
            if let Ok(dry_run_bool) = dry_run.downcast_ref::<bool>() {
                if *dry_run_bool {
                    command.arg("--dry-run");
                }
            }
        }
        
        if let Some(quiet) = options.get("quiet") {
            if let Ok(quiet_bool) = quiet.downcast_ref::<bool>() {
                if *quiet_bool {
                    command.arg("-qq");
                }
            }
        }
        
        // Execute upgrade
        match command.output() {
            Ok(output) => {
                if output.status.success() {
                    tracing::info!("System upgrade completed successfully");
                    
                    // Check if there are packages to upgrade
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    if output_str.contains("packages will be upgraded") || output_str.contains("packages upgraded") {
                        tracing::info!("Packages were upgraded");
                    } else {
                        tracing::info!("No packages needed upgrading");
                    }
                } else {
                    let stderr = String::from_utf8_lossy(&output.stderr);
                    tracing::warn!("System upgrade failed: {}", stderr);
                }
            }
            Err(e) => {
                tracing::error!("Failed to execute apt upgrade: {}", e);
            }
        }
        
        Ok(transaction_id)
    }

    /// Rollback the system
    async fn rollback(&self, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Rolling back system with options: {:?}", options);
        
        // Generate transaction ID
        let transaction_id = format!("rollback_{}", chrono::Utc::now().timestamp());
        
        // Check if we're in an OSTree system
        let ostree_status = std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output();
        
        match ostree_status {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    
                    // Find the previous deployment (not the current booted one)
                    let deployments: Vec<&str> = output_str.lines()
                        .filter(|line| !line.contains("*") && line.trim().len() > 0)
                        .collect();
                    
                    if deployments.len() > 1 {
                        // Get the previous deployment (second in the list)
                        let previous_deployment = deployments[1];
                        let parts: Vec<&str> = previous_deployment.split_whitespace().collect();
                        
                        if parts.len() >= 2 {
                            let deployment_id = parts[0];
                            let deployment_commit = parts[1];
                            
                            tracing::info!("Rolling back to deployment: {} (commit: {})", deployment_id, deployment_commit);
                            
                            // Execute rollback using ostree admin deploy
                            let rollback_output = std::process::Command::new("ostree")
                                .arg("admin")
                                .arg("deploy")
                                .arg("--os")
                                .arg(deployment_id)
                                .arg(deployment_commit)
                                .output();
                            
                            match rollback_output {
                                Ok(output) => {
                                    if output.status.success() {
                                        tracing::info!("Rollback completed successfully");
                                        
                                        // Check if reboot is requested
                                        if let Some(reboot) = options.get("reboot") {
                                            if let Ok(reboot_bool) = reboot.downcast_ref::<bool>() {
                                                if *reboot_bool {
                                                    tracing::info!("Reboot requested after rollback");
                                                    // In a real implementation, this would trigger a reboot
                                                }
                                            }
                                        }
                                    } else {
                                        let stderr = String::from_utf8_lossy(&output.stderr);
                                        tracing::error!("Rollback failed: {}", stderr);
                                    }
                                }
                                Err(e) => {
                                    tracing::error!("Failed to execute rollback: {}", e);
                                }
                            }
                        } else {
                            tracing::warn!("Could not parse previous deployment information");
                        }
                    } else {
                        tracing::warn!("No previous deployment available for rollback");
                    }
                } else {
                    tracing::error!("Failed to get OSTree status");
                }
            }
            Err(e) => {
                tracing::error!("OSTree not available: {}", e);
            }
        }
        
        Ok(transaction_id)
    }

    /// Rebase to a different reference
    async fn rebase(&self, refspec: String, packages: Vec<String>, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Rebasing to refspec: {} with packages: {:?} and options: {:?}", refspec, refspec, packages, options);
        
        // Generate transaction ID
        let transaction_id = format!("rebase_{}", chrono::Utc::now().timestamp());
        
        // Parse refspec (format: remote:branch or just branch)
        let (remote, branch) = if refspec.contains(':') {
            let parts: Vec<&str> = refspec.splitn(2, ':').collect();
            (parts[0], parts[1])
        } else {
            ("origin", refspec.as_str())
        };
        
        tracing::info!("Rebasing to remote: {}, branch: {}", remote, branch);
        
        // Check if we're in an OSTree system
        let ostree_status = std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output();
        
        match ostree_status {
            Ok(output) => {
                if output.status.success() {
                    // Get current deployment info
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    let current_deployment = output_str.lines()
                        .find(|line| line.contains("*"))
                        .and_then(|line| {
                            let parts: Vec<&str> = line.split_whitespace().collect();
                            if parts.len() >= 2 {
                                Some((parts[1], parts[2]))
                            } else {
                                None
                            }
                        });
                    
                    if let Some((current_os, current_commit)) = current_deployment {
                        tracing::info!("Current deployment: {} (commit: {})", current_os, current_commit);
                        
                        // Execute rebase using ostree admin deploy
                        let mut rebase_command = std::process::Command::new("ostree");
                        rebase_command.arg("admin")
                            .arg("deploy")
                            .arg("--os")
                            .arg(current_os)
                            .arg(&format!("{}:{}", remote, branch));
                        
                        // Add options
                        if let Some(dry_run) = options.get("dry_run") {
                            if let Ok(dry_run_bool) = dry_run.downcast_ref::<bool>() {
                                if *dry_run_bool {
                                    rebase_command.arg("--dry-run");
                                }
                            }
                        }
                        
                        let rebase_output = rebase_command.output();
                        
                        match rebase_output {
                            Ok(output) => {
                                if output.status.success() {
                                    tracing::info!("Rebase completed successfully");
                                    
                                    // Handle package installation if specified
                                    if !packages.is_empty() {
                                        tracing::info!("Installing additional packages: {:?}", packages);
                                        
                                        let mut install_command = std::process::Command::new("apt");
                                        install_command.arg("install");
                                        install_command.args(&packages);
                                        
                                        if let Some(quiet) = options.get("quiet") {
                                            if let Ok(quiet_bool) = quiet.downcast_ref::<bool>() {
                                                if *quiet_bool {
                                                    install_command.arg("-qq");
                                                }
                                            }
                                        }
                                        
                                        match install_command.output() {
                                            Ok(install_output) => {
                                                if install_output.status.success() {
                                                    tracing::info!("Additional packages installed successfully");
                                                } else {
                                                    let stderr = String::from_utf8_lossy(&install_output.stderr);
                                                    tracing::warn!("Package installation failed: {}", stderr);
                                                }
                                            }
                                            Err(e) => {
                                                tracing::error!("Failed to install packages: {}", e);
                                            }
                                        }
                                    }
                                    
                                    // Check if reboot is requested
                                    if let Some(reboot) = options.get("reboot") {
                                        if let Ok(reboot_bool) = reboot.downcast_ref::<bool>() {
                                            if *reboot_bool {
                                                tracing::info!("Reboot requested after rebase");
                                                // In a real implementation, this would trigger a reboot
                                            }
                                        }
                                    }
                                } else {
                                    let stderr = String::from_utf8_lossy(&output.stderr);
                                    tracing::error!("Rebase failed: {}", stderr);
                                }
                            }
                            Err(e) => {
                                tracing::error!("Failed to execute rebase: {}", e);
                            }
                        }
                    } else {
                        tracing::error!("Could not determine current deployment");
                    }
                } else {
                    tracing::error!("Failed to get OSTree status");
                }
            }
            Err(e) => {
                tracing::error!("OSTree not available: {}", e);
            }
        }
        
        Ok(transaction_id)
    }

    /// Change packages (install/remove)
    async fn pkg_change(&self, options: HashMap<String, zbus::zvariant::Value>, packages_added: Vec<String>, packages_removed: Vec<String>) -> fdo::Result<String> {
        tracing::info!("Changing packages - added: {:?}, removed: {:?}, options: {:?}", packages_added, packages_removed, options);
        
        // Generate transaction ID
        let transaction_id = format!("pkg_change_{}", chrono::Utc::now().timestamp());
        
        // Handle package installation
        if !packages_added.is_empty() {
            let mut command = std::process::Command::new("apt");
            command.arg("install");
            
            // Add options
            if let Some(dry_run) = options.get("dry_run") {
                if let Ok(dry_run_bool) = dry_run.downcast_ref::<bool>() {
                    if *dry_run_bool {
                        command.arg("--dry-run");
                    }
                }
            }
            
            // Add packages to install
            command.args(&packages_added);
            
            match command.output() {
                Ok(output) => {
                    if output.status.success() {
                        tracing::info!("Package installation completed successfully");
                    } else {
                        let stderr = String::from_utf8_lossy(&output.stderr);
                        tracing::warn!("Package installation failed: {}", stderr);
                    }
                }
                Err(e) => {
                    tracing::error!("Failed to execute apt install: {}", e);
                }
            }
        }
        
        // Handle package removal
        if !packages_removed.is_empty() {
            let mut command = std::process::Command::new("apt");
            command.arg("remove");
            
            // Add options
            if let Some(dry_run) = options.get("dry_run") {
                if let Ok(dry_run_bool) = dry_run.downcast_ref::<bool>() {
                    if *dry_run_bool {
                        command.arg("--dry-run");
                    }
                }
            }
            
            // Add packages to remove
            command.args(&packages_removed);
            
            match command.output() {
                Ok(output) => {
                    if output.status.success() {
                        tracing::info!("Package removal completed successfully");
                    } else {
                        let stderr = String::from_utf8_lossy(&output.stderr);
                        tracing::warn!("Package removal failed: {}", stderr);
                    }
                }
                Err(e) => {
                    tracing::error!("Failed to execute apt remove: {}", e);
                }
            }
        }
        
        Ok(transaction_id)
    }

    /// Set initramfs state
    async fn set_initramfs_state(&self, regenerate: bool, args: Vec<String>, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Setting initramfs state - regenerate: {}, args: {:?}, options: {:?}", regenerate, regenerate, args, options);
        
        // Generate transaction ID
        let transaction_id = format!("initramfs_{}", chrono::Utc::now().timestamp());
        
        if regenerate {
            tracing::info!("Regenerating initramfs...");
            
            // Check if we're in an OSTree system
            let ostree_status = std::process::Command::new("ostree")
                .arg("admin")
                .arg("status")
                .output();
            
            match ostree_status {
                Ok(output) => {
                    if output.status.success() {
                        // Get current deployment info
                        let output_str = String::from_utf8_lossy(&output.stdout);
                        let current_deployment = output_str.lines()
                            .find(|line| line.contains("*"))
                            .and_then(|line| {
                                let parts: Vec<&str> = line.split_whitespace().collect();
                                if parts.len() >= 2 {
                                    Some((parts[1], parts[2]))
                                } else {
                                    None
                                }
                            });
                        
                        if let Some((current_os, current_commit)) = current_deployment {
                            tracing::info!("Regenerating initramfs for deployment: {} (commit: {})", current_os, current_commit);
                            
                            // Execute initramfs regeneration using ostree admin initramfs
                            let mut initramfs_command = std::process::Command::new("ostree");
                            initramfs_command.arg("admin")
                                .arg("initramfs")
                                .arg("--os")
                                .arg(current_os);
                            
                            // Add additional arguments if specified
                            if !args.is_empty() {
                                initramfs_command.args(&args);
                            }
                            
                            // Add options
                            if let Some(force) = options.get("force") {
                                if let Ok(force_bool) = force.downcast_ref::<bool>() {
                                    if *force_bool {
                                        initramfs_command.arg("--force");
                                    }
                                }
                            }
                            
                            let initramfs_output = initramfs_command.output();
                            
                            match initramfs_output {
                                Ok(output) => {
                                    if output.status.success() {
                                        tracing::info!("Initramfs regeneration completed successfully");
                                    } else {
                                        let stderr = String::from_utf8_lossy(&output.stderr);
                                        tracing::error!("Initramfs regeneration failed: {}", stderr);
                                    }
                                }
                                Err(e) => {
                                    tracing::error!("Failed to execute initramfs regeneration: {}", e);
                                }
                            }
                        } else {
                            tracing::error!("Could not determine current deployment");
                        }
                    } else {
                        tracing::error!("Failed to get OSTree status");
                    }
                }
                Err(e) => {
                    tracing::error!("OSTree not available: {}", e);
                }
            }
        } else {
            tracing::info!("Initramfs regeneration not requested");
        }
        
        Ok(transaction_id)
    }

    /// Modify kernel arguments
    async fn kernel_args(&self, existing_args: String, args_added: Vec<String>, args_replaced: Vec<String>, args_removed: Vec<String>, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Modifying kernel args - existing: {}, added: {:?}, replaced: {:?}, removed: {:?}, options: {:?}", 
            existing_args, args_added, args_replaced, args_removed, options);
        
        // Generate transaction ID
        let transaction_id = format!("kargs_{}", chrono::Utc::now().timestamp());
        
        // Check if we're in an OSTree system
        let ostree_status = std::process::Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output();
        
        match ostree_status {
            Ok(output) => {
                if output.status.success() {
                    // Get current deployment info
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    let current_deployment = output_str.lines()
                        .find(|line| line.contains("*"))
                        .and_then(|line| {
                            let parts: Vec<&str> = line.split_whitespace().collect();
                            if parts.len() >= 2 {
                                Some((parts[1], parts[2]))
                            } else {
                                None
                            }
                        });
                    
                    if let Some((current_os, current_commit)) = current_deployment {
                        tracing::info!("Modifying kernel args for deployment: {} (commit: {})", current_os, current_commit);
                        
                        // Build new kernel arguments
                        let mut new_args = existing_args;
                        
                        // Remove arguments
                        for arg in &args_removed {
                            new_args = new_args.replace(arg, "");
                        }
                        
                        // Replace arguments
                        for (old_arg, new_arg) in args_replaced.chunks(2) {
                            if args_replaced.len() >= 2 {
                                new_args = new_args.replace(old_arg, new_arg);
                            }
                        }
                        
                        // Add new arguments
                        for arg in &args_added {
                            if !new_args.contains(arg) {
                                if !new_args.is_empty() {
                                    new_args.push(' ');
                                }
                                new_args.push_str(arg);
                            }
                        }
                        
                        // Clean up multiple spaces
                        new_args = new_args.split_whitespace().collect::<Vec<&str>>().join(" ");
                        
                        tracing::info!("New kernel arguments: {}", new_args);
                        
                        // Execute kernel argument modification using ostree admin kargs
                        let mut kargs_command = std::process::Command::new("ostree");
                        kargs_command.arg("admin")
                            .arg("kargs")
                            .arg("--os")
                            .arg(current_os);
                        
                        // Add options
                        if let Some(force) = options.get("force") {
                            if let Ok(force_bool) = force.downcast_ref::<bool>() {
                                if *force_bool {
                                    kargs_command.arg("--force");
                                }
                            }
                        }
                        
                        // Set the new kernel arguments
                        kargs_command.arg("--set");
                        kargs_command.arg(&new_args);
                        
                        let kargs_output = kargs_command.output();
                        
                        match kargs_output {
                            Ok(output) => {
                                if output.status.success() {
                                    tracing::info!("Kernel arguments modified successfully");
                                    
                                    // Check if reboot is requested
                                    if let Some(reboot) = options.get("reboot") {
                                        if let Ok(reboot_bool) = reboot.downcast_ref::<bool>() {
                                            if *reboot_bool {
                                                tracing::info!("Reboot requested after kernel argument modification");
                                                // In a real implementation, this would trigger a reboot
                                            }
                                        }
                                    }
                                } else {
                                    let stderr = String::from_utf8_lossy(&output.stderr);
                                    tracing::error!("Kernel argument modification failed: {}", stderr);
                                }
                            }
                            Err(e) => {
                                tracing::error!("Failed to execute kernel argument modification: {}", e);
                            }
                        }
                    } else {
                        tracing::error!("Could not determine current deployment");
                    }
                } else {
                    tracing::error!("Failed to get OSTree status");
                }
            }
            Err(e) => {
                tracing::error!("OSTree not available: {}", e);
            }
        }
        
        Ok(transaction_id)
    }

    /// Cleanup operations
    async fn cleanup(&self, operations: Vec<String>) -> fdo::Result<String> {
        tracing::info!("Cleaning up operations: {:?}", operations);
        
        // Generate transaction ID
        let transaction_id = format!("cleanup_{}", chrono::Utc::now().timestamp());
        
        for operation in &operations {
            match operation.as_str() {
                "old-deployments" => {
                    tracing::info!("Cleaning up old deployments...");
                    
                    // Use ostree admin cleanup to remove old deployments
                    let cleanup_output = std::process::Command::new("ostree")
                        .arg("admin")
                        .arg("cleanup")
                        .arg("--keep")
                        .arg("2") // Keep only 2 most recent deployments
                        .output();
                    
                    match cleanup_output {
                        Ok(output) => {
                            if output.status.success() {
                                tracing::info!("Old deployments cleaned up successfully");
                            } else {
                                let stderr = String::from_utf8_lossy(&output.stderr);
                                tracing::warn!("Failed to cleanup old deployments: {}", stderr);
                            }
                        }
                        Err(e) => {
                            tracing::error!("Failed to execute deployment cleanup: {}", e);
                        }
                    }
                }
                "apt-cache" => {
                    tracing::info!("Cleaning up APT cache...");
                    
                    // Use apt clean to remove package cache
                    let apt_clean_output = std::process::Command::new("apt")
                        .arg("clean")
                        .output();
                    
                    match apt_clean_output {
                        Ok(output) => {
                            if output.status.success() {
                                tracing::info!("APT cache cleaned up successfully");
                            } else {
                                let stderr = String::from_utf8_lossy(&output.stderr);
                                tracing::warn!("Failed to cleanup APT cache: {}", stderr);
                            }
                        }
                        Err(e) => {
                            tracing::error!("Failed to execute APT cache cleanup: {}", e);
                        }
                    }
                }
                "temp-files" => {
                    tracing::info!("Cleaning up temporary files...");
                    
                    // Clean up common temporary directories
                    let temp_dirs = ["/tmp", "/var/tmp"];
                    for temp_dir in &temp_dirs {
                        if let Ok(entries) = std::fs::read_dir(temp_dir) {
                            let mut cleaned_count = 0;
                            for entry in entries.flatten() {
                                if let Ok(metadata) = entry.metadata() {
                                    if let Ok(modified) = metadata.modified() {
                                        let age = chrono::Utc::now()
                                            .signed_duration_since(chrono::DateTime::from(modified))
                                            .num_hours();
                                        
                                        // Remove files older than 24 hours
                                        if age > 24 {
                                            if let Err(e) = std::fs::remove_file(entry.path()) {
                                                tracing::warn!("Failed to remove old temp file: {}", e);
                                            } else {
                                                cleaned_count += 1;
                                            }
                                        }
                                    }
                                }
                            }
                            tracing::info!("Cleaned up {} old files from {}", cleaned_count, temp_dir);
                        }
                    }
                }
                "log-files" => {
                    tracing::info!("Cleaning up old log files...");
                    
                    // Clean up old log files
                    let log_dirs = ["/var/log"];
                    for log_dir in &log_dirs {
                        if let Ok(entries) = std::fs::read_dir(log_dir) {
                            let mut cleaned_count = 0;
                            for entry in entries.flatten() {
                                if let Some(ext) = entry.path().extension() {
                                    if ext == "gz" || ext == "old" || ext == "1" || ext == "2" {
                                        if let Err(e) = std::fs::remove_file(entry.path()) {
                                            tracing::warn!("Failed to remove old log file: {}", e);
                                        } else {
                                            cleaned_count += 1;
                                        }
                                    }
                                }
                            }
                            tracing::info!("Cleaned up {} old log files from {}", cleaned_count, log_dir);
                        }
                    }
                }
                _ => {
                    tracing::warn!("Unknown cleanup operation: {}", operation);
                }
            }
        }
        
        tracing::info!("Cleanup operations completed");
        Ok(transaction_id)
    }

    /// Refresh metadata
    async fn refresh_md(&self, options: HashMap<String, zbus::zvariant::Value>) -> fdo::Result<String> {
        tracing::info!("Refreshing metadata with options: {:?}", options);
        
        // Generate transaction ID
        let transaction_id = format!("refresh_md_{}", chrono::Utc::now().timestamp());
        
        // Use apt update to refresh package metadata
        let mut command = std::process::Command::new("apt");
        command.arg("update");
        
        // Add options if specified
        if let Some(quiet) = options.get("quiet") {
            if let Ok(quiet_bool) = quiet.downcast_ref::<bool>() {
                if *quiet_bool {
                    command.arg("-qq");
                }
            }
        }
        
        match command.output() {
            Ok(output) => {
                if output.status.success() {
                    tracing::info!("Metadata refresh completed successfully");
                    Ok(transaction_id)
                } else {
                    let stderr = String::from_utf8_lossy(&output.stderr);
                    tracing::warn!("Metadata refresh failed: {}", stderr);
                    // Still return transaction ID for tracking
                    Ok(transaction_id)
                }
            }
            Err(e) => {
                tracing::error!("Failed to execute apt update: {}", e);
                // Return transaction ID even on failure for tracking
                Ok(transaction_id)
            }
        }
    }

    /// Get packages information
    async fn get_packages(&self, packages: Vec<String>) -> fdo::Result<Vec<HashMap<String, zbus::zvariant::Value>>> {
        tracing::info!("Getting packages information: {:?}", packages);
        let mut result = Vec::new();
        
        for package in &packages {
            let mut pkg_info = HashMap::new();
            pkg_info.insert("name".to_string(), zbus::zvariant::Value::Str(package.clone()));
            
            // Get package information using apt show
            let apt_show_output = std::process::Command::new("apt")
                .arg("show")
                .arg(package)
                .output();
            
            match apt_show_output {
                Ok(output) => {
                    if output.status.success() {
                        let output_str = String::from_utf8_lossy(&output.stdout);
                        
                        // Parse package information
                        for line in output_str.lines() {
                            if line.starts_with("Version: ") {
                                let version = line[9..].trim();
                                pkg_info.insert("version".to_string(), zbus::zvariant::Value::Str(version.to_string()));
                            } else if line.starts_with("Description: ") {
                                let description = line[13..].trim();
                                pkg_info.insert("description".to_string(), zbus::zvariant::Value::Str(description.to_string()));
                            } else if line.starts_with("Depends: ") {
                                let depends = line[9..].trim();
                                pkg_info.insert("depends".to_string(), zbus::zvariant::Value::Str(depends.to_string()));
                            } else if line.starts_with("Installed-Size: ") {
                                let size = line[16..].trim();
                                pkg_info.insert("size".to_string(), zbus::zvariant::Value::Str(size.to_string()));
                            } else if line.starts_with("Priority: ") {
                                let priority = line[10..].trim();
                                pkg_info.insert("priority".to_string(), zbus::zvariant::Value::Str(priority.to_string()));
                            }
                        }
                        
                        // Check if package is installed
                        let dpkg_status = std::process::Command::new("dpkg")
                            .arg("-s")
                            .arg(package)
                            .output();
                        
                        match dpkg_status {
                            Ok(status_output) => {
                                if status_output.status.success() {
                                    pkg_info.insert("installed".to_string(), zbus::zvariant::Value::Bool(true));
                                } else {
                                    pkg_info.insert("installed".to_string(), zbus::zvariant::Value::Bool(false));
                                }
                            }
                            Err(_) => {
                                pkg_info.insert("installed".to_string(), zbus::zvariant::Value::Bool(false));
                            }
                        }
                    } else {
                        // Package not found, use fallback information
                        pkg_info.insert("version".to_string(), zbus::zvariant::Value::Str("not found".to_string()));
                        pkg_info.insert("description".to_string(), zbus::zvariant::Value::Str("Package not available".to_string()));
                        pkg_info.insert("installed".to_string(), zbus::zvariant::Value::Bool(false));
                    }
                }
                Err(e) => {
                    tracing::warn!("Failed to get package information for {}: {}", package, e);
                    // Use fallback information
                    pkg_info.insert("version".to_string(), zbus::zvariant::Value::Str("error".to_string()));
                    pkg_info.insert("description".to_string(), zbus::zvariant::Value::Str("Failed to retrieve package information".to_string()));
                    pkg_info.insert("installed".to_string(), zbus::zvariant::Value::Bool(false));
                }
            }
            
            result.push(pkg_info);
        }
        
        Ok(result)
    }

    /// Search packages
    async fn search(&self, query: Vec<String>) -> fdo::Result<Vec<HashMap<String, zbus::zvariant::Value>>> {
        tracing::info!("Searching packages with query: {:?}", query);
        let mut result = Vec::new();
        
        // Join query terms for apt search
        let search_query = query.join(" ");
        
        // Use apt search to find packages
        match std::process::Command::new("apt")
            .arg("search")
            .arg(&search_query)
            .output() {
            Ok(output) => {
                if output.status.success() {
                    let output_str = String::from_utf8_lossy(&output.stdout);
                    
                    // Parse apt search output
                    for line in output_str.lines() {
                        if line.contains("/") && !line.starts_with("Sorting") && !line.starts_with("Done") {
                            // Parse line like "package-name/stable,now 1.2.3-4 amd64 [installed] Description"
                            let parts: Vec<&str> = line.splitn(2, '/').collect();
                            if parts.len() >= 2 {
                                let package_name = parts[0].trim();
                                let rest = parts[1];
                                
                                // Extract version and description
                                let version_parts: Vec<&str> = rest.splitn(2, ' ').collect();
                                let version = if version_parts.len() >= 1 {
                                    version_parts[0].trim()
                                } else {
                                    "unknown"
                                };
                                
                                let description = if version_parts.len() >= 2 {
                                    version_parts[1].trim()
                                } else {
                                    "No description available"
                                };
                                
                                let mut pkg_info = HashMap::new();
                                pkg_info.insert("name".to_string(), zbus::zvariant::Value::Str(package_name.to_string()));
                                pkg_info.insert("version".to_string(), zbus::zvariant::Value::Str(version.to_string()));
                                pkg_info.insert("description".to_string(), zbus::zvariant::Value::Str(description.to_string()));
                                
                                result.push(pkg_info);
                            }
                        }
                    }
                } else {
                    // Command failed, return error info
                    let stderr = String::from_utf8_lossy(&output.stderr);
                    tracing::warn!("apt search failed: {}", stderr);
                    
                    // Return empty result instead of error
                    let mut error_info = HashMap::new();
                    error_info.insert("name".to_string(), zbus::zvariant::Value::Str("search-error".to_string()));
                    error_info.insert("description".to_string(), zbus::zvariant::Value::Str(format!("Search failed: {}", stderr)));
                    result.push(error_info);
                }
            }
            Err(e) => {
                // Command not found or failed
                tracing::warn!("apt search command failed: {}", e);
                
                let mut error_info = HashMap::new();
                error_info.insert("name".to_string(), zbus::zvariant::Value::Str("search-error".to_string()));
                error_info.insert("description".to_string(), zbus::zvariant::Value::Str(format!("Search command failed: {}", e)));
                result.push(error_info);
            }
        }
        
        Ok(result)
    }
}

/// Transaction Interface - Transaction management
#[dbus_interface(name = "org.projectatomic.aptostree1.Transaction")]
impl DaemonDBus {
    /// Get transaction title
    #[dbus_interface(property)]
    async fn title(&self) -> fdo::Result<String> {
        // Get the current active transaction title
        let transaction_manager = self.transaction_manager.read().await;
        if let Some(active_transaction) = transaction_manager.get_active_transaction() {
            match active_transaction.transaction_type {
                TransactionType::Install => Ok("Package Installation".to_string()),
                TransactionType::Remove => Ok("Package Removal".to_string()),
                TransactionType::Upgrade => Ok("System Upgrade".to_string()),
                TransactionType::Rollback => Ok("System Rollback".to_string()),
                TransactionType::Deploy => Ok("Deployment".to_string()),
                TransactionType::Rebase => Ok("System Rebase".to_string()),
            }
        } else {
            Ok("No Active Transaction".to_string())
        }
    }

    /// Get initiating client description
    #[dbus_interface(property)]
    async fn initiating_client_description(&self) -> fdo::Result<String> {
        // Get the client that initiated the current transaction
        let transaction_manager = self.transaction_manager.read().await;
        if let Some(active_transaction) = transaction_manager.get_active_transaction() {
            let clients = self.clients.lock().await;
            if let Some(client_info) = clients.get(&active_transaction.client_id) {
                Ok(client_info.description.clone())
            } else {
                Ok("Unknown Client".to_string())
            }
        } else {
            Ok("No Active Transaction".to_string())
        }
    }

    /// Cancel the transaction
    async fn cancel(&self) -> fdo::Result<bool> {
        tracing::info!("Cancelling transaction");
        
        let mut transaction_manager = self.transaction_manager.write().await;
        if let Some(active_transaction) = transaction_manager.get_active_transaction_mut() {
            // Update transaction state
            active_transaction.state = TransactionState::Cancelled;
            active_transaction.end_time = Some(chrono::Utc::now());
            
            // Clean up any temporary resources
            tracing::info!("Transaction cancelled successfully");
            Ok(true)
        } else {
            tracing::warn!("No active transaction to cancel");
            Ok(false)
        }
    }

    /// Start the transaction
    async fn start(&self) -> fdo::Result<bool> {
        tracing::info!("Starting transaction");
        
        let mut transaction_manager = self.transaction_manager.write().await;
        if let Some(active_transaction) = transaction_manager.get_active_transaction_mut() {
            // Update transaction state
            active_transaction.state = TransactionState::Running;
            active_transaction.start_time = Some(chrono::Utc::now());
            
            tracing::info!("Transaction started successfully");
            Ok(true)
        } else {
            tracing::warn!("No active transaction to start");
            Ok(false)
        }
    }

    /// Signal: Transaction finished
    #[dbus_interface(signal)]
    async fn finished(&self, success: bool, message: String) -> zbus::Result<()>;

    /// Signal: Transaction message
    #[dbus_interface(signal)]
    async fn message(&self, message: String) -> zbus::Result<()>;

    /// Signal: Task begin
    #[dbus_interface(signal)]
    async fn task_begin(&self, task_name: String) -> zbus::Result<()>;

    /// Signal: Task end
    #[dbus_interface(signal)]
    async fn task_end(&self, task_name: String) -> zbus::Result<()>;

    /// Signal: Progress percentage
    #[dbus_interface(signal)]
    async fn percent_progress(&self, task_name: String, percentage: u32) -> zbus::Result<()>;

    /// Signal: Progress end
    #[dbus_interface(signal)]
    async fn progress_end(&self) -> zbus::Result<()>;
}

impl TransactionType {
    fn from_str(s: &str) -> Result<Self, DaemonError> {
        match s {
            "install" => Ok(TransactionType::Install),
            "remove" => Ok(TransactionType::Remove),
            "upgrade" => Ok(TransactionType::Upgrade),
            "rollback" => Ok(TransactionType::Rollback),
            "deploy" => Ok(TransactionType::Deploy),
            "rebase" => Ok(TransactionType::Rebase),
            _ => Err(DaemonError::Configuration(format!("Unknown transaction type: {}", s))),
        }
    }
}
