use crate::lib::error::{AptOstreeError, AptOstreeResult};
use crate::lib::transaction::{TransactionManager, TransactionType, TransactionState, TransactionResult};
use crate::lib::security::SecurityManager;
use std::process::Command;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;

/// Package manager for apt-ostree
pub struct PackageManager {
    cache_updated: bool,
    transaction_manager: Arc<TransactionManager>,
    security_manager: Arc<SecurityManager>,
}

impl PackageManager {
    /// Create a new package manager instance
    pub fn new() -> AptOstreeResult<Self> {
        Ok(Self {
            cache_updated: false,
            transaction_manager: Arc::new(TransactionManager::new()),
            security_manager: Arc::new(SecurityManager::new()?),
        })
    }
    
    /// Install a package with transaction support and security authorization
    pub async fn install_package(&self, package_name: &str) -> AptOstreeResult<()> {
        // Check if operation requires authorization
        if self.security_manager.requires_authorization("install") {
            // Check Polkit authorization
            let user_id = self.security_manager.get_current_user_id()?;
            let authorized = self.security_manager.authorize_package_install(user_id, &[package_name.to_string()]).await?;
            
            if !authorized {
                return Err(AptOstreeError::PermissionDenied(
                    format!("User {} is not authorized to install packages", user_id)
                ));
            }
        }
        
        // Create a transaction for package installation
        let transaction_id = self.transaction_manager
            .create_transaction(
                TransactionType::PkgChange,
                self.get_current_user_id()?,
                self.get_session_id()?,
                format!("Install package: {}", package_name),
                format!("Installing package {} and its dependencies", package_name),
            )
            .await?;
        
        // Get the transaction and update its state
        let mut transaction = self.transaction_manager.get_transaction(&transaction_id).await?;
        transaction.update_state(TransactionState::Preparing);
        transaction.update_progress(0.1);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // First check if package exists and get its information
        let package_info = self.get_package_info(package_name)?;
        
        transaction.update_progress(0.2);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        println!("Installing package: {} (version: {})", package_info.name, package_info.version);
        println!("Description: {}", package_info.description);
        
        if !package_info.depends.is_empty() {
            println!("Dependencies: {}", package_info.depends.join(", "));
        }
        
        // Check if we're on an OSTree system
        if !self.is_ostree_system()? {
            println!("Warning: Not on an OSTree system, using traditional package installation");
            transaction.update_progress(0.3);
            self.transaction_manager.update_transaction(&transaction).await?;
            
            let result = self.install_package_traditional(&package_info);
            
            // Update transaction with result
            transaction.update_state(if result.is_ok() { TransactionState::Completed } else { TransactionState::Failed });
            transaction.update_progress(1.0);
            transaction.set_result(TransactionResult {
                success: result.is_ok(),
                message: if result.is_ok() { "Package installed successfully".to_string() } else { "Package installation failed".to_string() },
                details: None,
                rollback_required: false,
            });
            self.transaction_manager.update_transaction(&transaction).await?;
            
            return result;
        }
        
        // Implement OSTree-based package layering
        println!("Implementing OSTree-based package layering...");
        
        transaction.update_state(TransactionState::Running);
        transaction.update_progress(0.4);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 1. Create a temporary working directory
        let temp_dir = tempfile::tempdir()
            .map_err(|e| AptOstreeError::System(format!("Failed to create temp directory: {}", e)))?;
        
        transaction.update_progress(0.5);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 2. Download the package and its dependencies
        let downloaded_packages = self.download_package_and_deps(&package_info)?;
        
        transaction.update_progress(0.6);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 3. Extract packages to the working directory
        self.extract_packages(&downloaded_packages, &temp_dir)?;
        
        transaction.update_progress(0.7);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 4. Create a new OSTree commit with the package
        let commit_hash = self.create_ostree_commit(&temp_dir, &package_info)?;
        
        transaction.update_progress(0.8);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 5. Update the current deployment to include the new package
        self.update_deployment_with_package(&package_info, &commit_hash)?;
        
        transaction.update_progress(1.0);
        transaction.update_state(TransactionState::Completed);
        transaction.set_result(TransactionResult {
            success: true,
            message: format!("Package {} successfully layered as OSTree commit: {}", package_name, commit_hash),
            details: Some(format!("Commit hash: {}", commit_hash)),
            rollback_required: false,
        });
        self.transaction_manager.update_transaction(&transaction).await?;
        
        println!("✅ Package {} successfully layered as OSTree commit: {}", package_name, commit_hash);
        
        Ok(())
    }
    
    /// Remove a package with transaction support and security authorization
    pub async fn remove_package(&self, package_name: &str) -> AptOstreeResult<()> {
        // Check if operation requires authorization
        if self.security_manager.requires_authorization("uninstall") {
            // Check Polkit authorization
            let user_id = self.security_manager.get_current_user_id()?;
            let authorized = self.security_manager.authorize_package_install(user_id, &[package_name.to_string()]).await?;
            
            if !authorized {
                return Err(AptOstreeError::PermissionDenied(
                    format!("User {} is not authorized to remove packages", user_id)
                ));
            }
        }
        
        // Check if package is actually installed
        if !self.is_package_installed(package_name)? {
            return Err(AptOstreeError::Apt(format!("Package {} is not installed", package_name)));
        }
        
        println!("Removing package: {}", package_name);
        
        // Create a transaction for package removal
        let transaction_id = self.transaction_manager
            .create_transaction(
                TransactionType::PkgChange,
                self.get_current_user_id()?,
                self.get_session_id()?,
                format!("Remove package: {}", package_name),
                format!("Removing package {} and cleaning up dependencies", package_name),
            )
            .await?;
        
        // Get the transaction and update its state
        let mut transaction = self.transaction_manager.get_transaction(&transaction_id).await?;
        transaction.update_state(TransactionState::Preparing);
        transaction.update_progress(0.1);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // Check if we're on an OSTree system
        if !self.is_ostree_system()? {
            println!("Warning: Not on an OSTree system, using traditional package removal");
            transaction.update_progress(0.3);
            self.transaction_manager.update_transaction(&transaction).await?;
            
            let result = self.remove_package_traditional(package_name);
            
            // Update transaction with result
            transaction.update_state(if result.is_ok() { TransactionState::Completed } else { TransactionState::Failed });
            transaction.update_progress(1.0);
            transaction.set_result(TransactionResult {
                success: result.is_ok(),
                message: if result.is_ok() { "Package removed successfully".to_string() } else { "Package removal failed".to_string() },
                details: None,
                rollback_required: false,
            });
            self.transaction_manager.update_transaction(&transaction).await?;
            
            return result;
        }
        
        // Implement OSTree-based package removal
        println!("Implementing OSTree-based package removal...");
        
        transaction.update_state(TransactionState::Running);
        transaction.update_progress(0.4);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 1. Get current deployment information
        let current_deployment = self.get_current_deployment_info()?;
        
        transaction.update_progress(0.5);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 2. Create a new deployment without the package
        let new_deployment = self.create_deployment_without_package(&current_deployment, package_name)?;
        
        transaction.update_progress(0.7);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 3. Deploy the new deployment
        self.deploy_new_deployment(&new_deployment)?;
        
        transaction.update_progress(0.9);
        self.transaction_manager.update_transaction(&transaction).await?;
        
        // 4. Clean up old deployment if successful
        self.cleanup_old_deployment(&current_deployment)?;
        
        transaction.update_progress(1.0);
        transaction.update_state(TransactionState::Completed);
        transaction.set_result(TransactionResult {
            success: true,
            message: format!("Package {} successfully removed from OSTree deployment", package_name),
            details: Some(format!("New deployment: {}", new_deployment)),
            rollback_required: false,
        });
        self.transaction_manager.update_transaction(&transaction).await?;
        
        println!("✅ Package {} successfully removed from OSTree deployment", package_name);
        
        Ok(())
    }
    
    /// Get package information
    pub fn get_package_info(&self, package_name: &str) -> AptOstreeResult<PackageInfo> {
        // Use apt-cache to get package information
        let output = Command::new("apt-cache")
            .arg("show")
            .arg(package_name)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to get package info: {}", e)))?;
        
        if !output.status.success() {
            return Err(AptOstreeError::Apt(format!("Package {} not found", package_name)));
        }
        
        let output_str = String::from_utf8_lossy(&output.stdout);
        self.parse_package_info(&output_str, package_name)
    }
    
    /// Check if a package is installed
    pub fn is_package_installed(&self, package_name: &str) -> AptOstreeResult<bool> {
        let output = Command::new("dpkg")
            .arg("-l")
            .arg(package_name)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to check package status: {}", e)))?;
        
        // dpkg -l returns 0 if package is installed, 1 if not
        Ok(output.status.success())
    }
    
    /// Search for packages
    pub fn search_packages(&self, query: &str) -> AptOstreeResult<Vec<PackageInfo>> {
        let output = Command::new("apt-cache")
            .arg("search")
            .arg(query)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to search packages: {}", e)))?;
        
        if !output.status.success() {
            return Ok(Vec::new());
        }
        
        let output_str = String::from_utf8_lossy(&output.stdout);
        let mut packages = Vec::new();
        
        for line in output_str.lines() {
            if let Some(package_name) = line.split_whitespace().next() {
                if let Ok(package_info) = self.get_package_info(package_name) {
                    packages.push(package_info);
                }
            }
        }
        
        Ok(packages)
    }
    
    /// Search for packages using regex pattern
    pub fn search_packages_regex(&self, pattern: &str) -> AptOstreeResult<Vec<PackageInfo>> {
        // For now, fall back to standard search since regex search is more complex
        // TODO: Implement proper regex search using regex crate
        println!("Warning: Regex search not yet implemented, using standard search");
        self.search_packages(pattern)
    }
    
    /// Search for packages with exact name matching
    pub fn search_packages_exact(&self, package_name: &str) -> AptOstreeResult<Vec<PackageInfo>> {
        // Try to get exact package info
        match self.get_package_info(package_name) {
            Ok(package_info) => Ok(vec![package_info]),
            Err(_) => {
                // If exact match fails, try to find similar packages
                let all_packages = self.search_packages(package_name)?;
                let exact_matches: Vec<PackageInfo> = all_packages
                    .into_iter()
                    .filter(|pkg| pkg.name == package_name)
                    .collect();
                Ok(exact_matches)
            }
        }
    }
    
    /// List installed packages
    pub fn list_installed_packages(&self) -> AptOstreeResult<Vec<PackageInfo>> {
        let output = Command::new("dpkg")
            .arg("-l")
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to list installed packages: {}", e)))?;
        
        if !output.status.success() {
            return Err(AptOstreeError::Apt("Failed to list installed packages".to_string()));
        }
        
        let output_str = String::from_utf8_lossy(&output.stdout);
        let mut packages = Vec::new();
        
        for line in output_str.lines() {
            if line.starts_with("ii") {
                let parts: Vec<&str> = line.split_whitespace().collect();
                if parts.len() >= 3 {
                    let package_name = parts[1];
                    if let Ok(package_info) = self.get_package_info(package_name) {
                        packages.push(package_info);
                    }
                }
            }
        }
        
        Ok(packages)
    }
    
    /// Update package cache
    pub fn update_cache(&mut self) -> AptOstreeResult<()> {
        println!("Updating package cache...");
        
        let output = Command::new("apt-get")
            .arg("update")
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to update package cache: {}", e)))?;
        
        if !output.status.success() {
            return Err(AptOstreeError::Apt("Failed to update package cache".to_string()));
        }
        
        self.cache_updated = true;
        println!("Package cache updated successfully");
        Ok(())
    }
    
    /// Parse package information from apt-cache show output
    fn parse_package_info(&self, output: &str, package_name: &str) -> AptOstreeResult<PackageInfo> {
        let mut info = PackageInfo {
            name: package_name.to_string(),
            version: "unknown".to_string(),
            description: "No description available".to_string(),
            depends: Vec::new(),
            size: 0,
            priority: "unknown".to_string(),
            section: "unknown".to_string(),
        };
        
        for line in output.lines() {
            if line.starts_with("Version: ") {
                info.version = line.strip_prefix("Version: ").unwrap_or("unknown").to_string();
            } else if line.starts_with("Description: ") {
                info.description = line.strip_prefix("Description: ").unwrap_or("No description available").to_string();
            } else if line.starts_with("Depends: ") {
                let deps = line.strip_prefix("Depends: ").unwrap_or("");
                info.depends = deps.split(", ")
                    .map(|s| s.split(" (").next().unwrap_or(s).trim().to_string())
                    .collect();
            } else if line.starts_with("Installed-Size: ") {
                if let Ok(size) = line.strip_prefix("Installed-Size: ").unwrap_or("0").parse::<u64>() {
                    info.size = size;
                }
            } else if line.starts_with("Priority: ") {
                info.priority = line.strip_prefix("Priority: ").unwrap_or("unknown").to_string();
            } else if line.starts_with("Section: ") {
                info.section = line.strip_prefix("Section: ").unwrap_or("unknown").to_string();
            }
        }
        
        Ok(info)
    }
    
    /// Get package dependencies
    pub fn get_package_dependencies(&self, package_name: &str) -> AptOstreeResult<Vec<String>> {
        let package_info = self.get_package_info(package_name)?;
        Ok(package_info.depends)
    }
    
    /// Check if package cache is up to date
    pub fn is_cache_updated(&self) -> bool {
        self.cache_updated
    }

    /// Check if we're running on an OSTree system
    fn is_ostree_system(&self) -> AptOstreeResult<bool> {
        // Check if /run/ostree-booted exists or if ostree admin status works
        if std::path::Path::new("/run/ostree-booted").exists() {
            return Ok(true);
        }
        
        // Try to run ostree admin status
        let output = Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output();
        
        Ok(output.is_ok() && output.unwrap().status.success())
    }
    
    /// Install package using traditional apt-get (fallback)
    fn install_package_traditional(&self, package_info: &PackageInfo) -> AptOstreeResult<()> {
        println!("Installing package using traditional apt-get...");
        
        let output = Command::new("apt-get")
            .arg("install")
            .arg("-y")
            .arg(&package_info.name)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to install package: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::Apt(format!("Package installation failed: {}", stderr)));
        }
        
        println!("✅ Package {} installed successfully using apt-get", package_info.name);
        Ok(())
    }
    
    /// Remove package using traditional apt-get (fallback)
    fn remove_package_traditional(&self, package_name: &str) -> AptOstreeResult<()> {
        println!("Removing package using traditional apt-get...");
        
        let output = Command::new("apt-get")
            .arg("remove")
            .arg("-y")
            .arg(package_name)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to remove package: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::Apt(format!("Package removal failed: {}", stderr)));
        }
        
        println!("✅ Package {} removed successfully using apt-get", package_name);
        Ok(())
    }
    
    /// Download package and its dependencies
    fn download_package_and_deps(&self, package_info: &PackageInfo) -> AptOstreeResult<Vec<String>> {
        println!("Downloading package and dependencies...");
        
        let mut packages_to_download = vec![package_info.name.clone()];
        packages_to_download.extend(package_info.depends.clone());
        
        // Use apt-get to download packages
        let output = Command::new("apt-get")
            .arg("download")
            .args(&packages_to_download)
            .output()
            .map_err(|e| AptOstreeError::Apt(format!("Failed to download packages: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::Apt(format!("Package download failed: {}", stderr)));
        }
        
        // Get list of downloaded .deb files
        let current_dir = std::env::current_dir()
            .map_err(|e| AptOstreeError::System(format!("Failed to get current directory: {}", e)))?;
        
        let deb_files: Vec<String> = std::fs::read_dir(current_dir)?
            .filter_map(|entry| {
                let entry = entry.ok()?;
                let path = entry.path();
                if path.extension()?.to_str()? == "deb" {
                    Some(path.to_string_lossy().to_string())
                } else {
                    None
                }
            })
            .collect();
        
        println!("Downloaded {} package files", deb_files.len());
        Ok(deb_files)
    }
    
    /// Extract packages to working directory
    fn extract_packages(&self, package_files: &[String], work_dir: &tempfile::TempDir) -> AptOstreeResult<()> {
        println!("Extracting packages to working directory...");
        
        for package_file in package_files {
            // Use dpkg-deb to extract package contents
            let output = Command::new("dpkg-deb")
                .arg("-R")
                .arg(package_file)
                .arg(work_dir.path())
                .output()
                .map_err(|e| AptOstreeError::Apt(format!("Failed to extract package {}: {}", package_file, e)))?;
            
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                return Err(AptOstreeError::Apt(format!("Package extraction failed: {}", stderr)));
            }
        }
        
        println!("Packages extracted successfully");
        Ok(())
    }
    
    /// Create OSTree commit with package contents
    fn create_ostree_commit(&self, work_dir: &tempfile::TempDir, package_info: &PackageInfo) -> AptOstreeResult<String> {
        println!("Creating OSTree commit with package {}...", package_info.name);
        
        // Get current OSTree commit
        let current_commit = self.get_current_ostree_commit()?;
        
        // Create a new branch for this package
        let branch_name = format!("packages/{}", package_info.name);
        
        // Use ostree commit to create a new commit
        let output = Command::new("ostree")
            .arg("commit")
            .arg("--branch")
            .arg(&branch_name)
            .arg("--tree")
            .arg(format!("dir={}", work_dir.path().display()))
            .arg("--subject")
            .arg(format!("Add package: {}", package_info.name))
            .arg("--body")
            .arg(format!("Package: {}\nVersion: {}\nDescription: {}", 
                        package_info.name, package_info.version, package_info.description))
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to create OSTree commit: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::System(format!("OSTree commit failed: {}", stderr)));
        }
        
        let commit_hash = String::from_utf8_lossy(&output.stdout).trim().to_string();
        println!("Created OSTree commit: {}", commit_hash);
        
        Ok(commit_hash)
    }
    
    /// Get current OSTree commit
    fn get_current_ostree_commit(&self) -> AptOstreeResult<String> {
        let output = Command::new("ostree")
            .arg("rev-parse")
            .arg("ostree/0/0")
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to get current commit: {}", e)))?;
        
        if !output.status.success() {
            return Err(AptOstreeError::System("Failed to get current OSTree commit".to_string()));
        }
        
        Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
    }
    
    /// Update deployment with new package
    fn update_deployment_with_package(&self, package_info: &PackageInfo, commit_hash: &str) -> AptOstreeResult<()> {
        println!("Updating deployment with package {}...", package_info.name);
        
        // Use ostree admin deploy to update the current deployment
        let output = Command::new("ostree")
            .arg("admin")
            .arg("deploy")
            .arg("--os")
            .arg("debian")
            .arg(commit_hash)
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to update deployment: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::System(format!("Deployment update failed: {}", stderr)));
        }
        
        println!("Deployment updated successfully");
        Ok(())
    }

    /// Get current deployment info
    fn get_current_deployment_info(&self) -> AptOstreeResult<String> {
        let output = Command::new("ostree")
            .arg("admin")
            .arg("status")
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to get current deployment info: {}", e)))?;
        
        if !output.status.success() {
            return Err(AptOstreeError::System("Failed to get current deployment info".to_string()));
        }
        
        let output_str = String::from_utf8_lossy(&output.stdout);
        // Look for the current deployment hash in the output
        for line in output_str.lines() {
            if line.contains("Deployment:") {
                let parts: Vec<&str> = line.split_whitespace().collect();
                if parts.len() > 1 {
                    return Ok(parts[1].to_string());
                }
            }
        }
        Err(AptOstreeError::System("Could not find current deployment hash".to_string()))
    }

    /// Create a new deployment without a specific package
    fn create_deployment_without_package(&self, current_deployment_hash: &str, package_name: &str) -> AptOstreeResult<String> {
        println!("Creating new deployment without package {}...", package_name);
        
        // Create a temporary directory for the new deployment
        let temp_dir = tempfile::tempdir()
            .map_err(|e| AptOstreeError::System(format!("Failed to create temp directory for new deployment: {}", e)))?;
        
        // Copy the current deployment tree
        let output = Command::new("ostree")
            .arg("admin")
            .arg("pull-local")
            .arg(format!("dir={}", temp_dir.path().display()))
            .arg(current_deployment_hash)
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to pull current deployment: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::System(format!("Failed to pull current deployment: {}", stderr)));
        }

        // Remove the package files from the new deployment
        let package_path = temp_dir.path().join("usr/lib/ostree-boot/deploy").join(package_name);
        if package_path.exists() {
            std::fs::remove_dir_all(&package_path)
                .map_err(|e| AptOstreeError::System(format!("Failed to remove package files from new deployment: {}", e)))?;
            println!("Removed package files from new deployment: {}", package_path.display());
        }

        // Create a new commit for the new deployment
        let new_commit_hash = self.create_ostree_commit(&temp_dir, &PackageInfo {
            name: package_name.to_string(),
            version: "0.0.0".to_string(), // Placeholder version
            description: "Package removed".to_string(),
            depends: Vec::new(),
            size: 0,
            priority: "unknown".to_string(),
            section: "unknown".to_string(),
        })?;

        println!("New deployment created without package {} (commit: {})", package_name, new_commit_hash);
        Ok(new_commit_hash)
    }

    /// Deploy the new deployment
    fn deploy_new_deployment(&self, new_deployment_hash: &str) -> AptOstreeResult<()> {
        println!("Deploying new deployment: {}", new_deployment_hash);
        
        let output = Command::new("ostree")
            .arg("admin")
            .arg("deploy")
            .arg("--os")
            .arg("debian")
            .arg(new_deployment_hash)
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to deploy new deployment: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::System(format!("Deployment deployment failed: {}", stderr)));
        }
        
        println!("New deployment deployed successfully");
        Ok(())
    }

    /// Clean up old deployment
    fn cleanup_old_deployment(&self, current_deployment_hash: &str) -> AptOstreeResult<()> {
        println!("Cleaning up old deployment: {}", current_deployment_hash);
        
        // Use ostree admin deploy to rollback to the previous deployment
        let output = Command::new("ostree")
            .arg("admin")
            .arg("deploy")
            .arg("--os")
            .arg("debian")
            .arg(current_deployment_hash)
            .output()
            .map_err(|e| AptOstreeError::System(format!("Failed to rollback to old deployment: {}", e)))?;
        
        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(AptOstreeError::System(format!("Deployment rollback failed: {}", stderr)));
        }
        
        println!("Old deployment cleaned up successfully");
        Ok(())
    }

    /// Get current user ID
    fn get_current_user_id(&self) -> AptOstreeResult<u32> {
        Ok(users::get_current_uid())
    }
    
    /// Get session ID
    fn get_session_id(&self) -> AptOstreeResult<String> {
        // Try to get session ID from environment or generate one
        Ok(std::env::var("XDG_SESSION_ID")
            .unwrap_or_else(|_| format!("session_{}", chrono::Utc::now().timestamp())))
    }
    
    /// Check if operation requires authorization
    pub fn requires_authorization(&self, operation: &str) -> bool {
        self.security_manager.requires_authorization(operation)
    }
    
    /// Check authorization for an operation
    pub async fn check_authorization(&self, operation: &str) -> AptOstreeResult<bool> {
        let user_id = self.security_manager.get_current_user_id()?;
        
        match operation {
            "install" | "uninstall" => {
                self.security_manager.authorize_package_install(user_id, &[]).await
            }
            "upgrade" => {
                self.security_manager.authorize_system_update(user_id).await
            }
            "rollback" => {
                self.security_manager.authorize_rollback(user_id).await
            }
            "deploy" => {
                self.security_manager.authorize_deployment(user_id).await
            }
            "rebase" => {
                self.security_manager.authorize_rebase(user_id).await
            }
            "kargs" => {
                self.security_manager.authorize_boot_config(user_id).await
            }
            "override" => {
                self.security_manager.authorize_package_override(user_id).await
            }
            "cleanup" => {
                self.security_manager.authorize_cleanup(user_id).await
            }
            "reload" => {
                self.security_manager.authorize_daemon_reload(user_id).await
            }
            _ => Ok(true) // Default to authorized for unknown operations
        }
    }
}

/// Package information
#[derive(Debug)]
pub struct PackageInfo {
    pub name: String,
    pub version: String,
    pub description: String,
    pub depends: Vec<String>,
    pub size: u64,
    pub priority: String,
    pub section: String,
}
