//! Progress tracking for package operations
//!
//! This module provides a callback-based progress tracking system for package installations
//! and uninstallations, allowing the CLI to display progress information.

use std::sync::Arc;
use std::sync::Mutex;

/// Represents the progress of a package operation
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProgressState {
    /// Preparing for installation/uninstallation
    Preparing,
    /// Downloading packages
    Downloading { current: usize, total: usize },
    /// Installing/uninstalling packages
    Installing { current: usize, total: usize },
    /// Operation completed
    Completed,
    /// Operation failed
    Failed(String),
}

/// Progress callback for package operations
pub trait ProgressCallback: Send + Sync {
    /// Called when progress is updated
    fn update(&self, state: ProgressState);
}

/// No-op progress callback (default)
pub struct NoOpProgressCallback;

impl ProgressCallback for NoOpProgressCallback {
    fn update(&self, _state: ProgressState) {}
}

/// Thread-safe progress tracker
pub struct ProgressTracker {
    callback: Arc<dyn ProgressCallback>,
}

impl ProgressTracker {
    /// Create a new progress tracker with a custom callback
    pub fn new(callback: Arc<dyn ProgressCallback>) -> Self {
        Self { callback }
    }

    /// Create a progress tracker with no-op callback
    pub fn noop() -> Self {
        Self {
            callback: Arc::new(NoOpProgressCallback),
        }
    }

    /// Update progress
    pub fn update(&self, state: ProgressState) {
        self.callback.update(state);
    }
}

impl Default for ProgressTracker {
    fn default() -> Self {
        Self::noop()
    }
}

/// Simple in-memory progress tracker for testing
pub struct MemoryProgressTracker {
    states: Arc<Mutex<Vec<ProgressState>>>,
}

impl MemoryProgressTracker {
    /// Create a new memory progress tracker
    pub fn new() -> Self {
        Self {
            states: Arc::new(Mutex::new(Vec::new())),
        }
    }

    /// Get all recorded states
    pub fn states(&self) -> Vec<ProgressState> {
        self.states.lock().unwrap().clone()
    }
}

impl Default for MemoryProgressTracker {
    fn default() -> Self {
        Self::new()
    }
}

impl ProgressCallback for MemoryProgressTracker {
    fn update(&self, state: ProgressState) {
        self.states.lock().unwrap().push(state);
    }
}
