//! Progress state and reporter trait.

use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};

use crate::types::CopyManifest;

/// Thread-safe progress counters updated atomically by worker tasks.
#[derive(Debug, Default)]
pub struct ProgressState {
    pub objects_discovered: AtomicU64,
    pub bytes_discovered: AtomicU64,
    pub objects_completed: AtomicU64,
    pub bytes_completed: AtomicU64,
    pub objects_failed: AtomicU64,
    pub objects_skipped: AtomicU64,
    pub current_concurrent: AtomicU32,
}

impl ProgressState {
    /// Take a snapshot of the current state.
    pub fn snapshot(&self) -> ProgressSnapshot {
        ProgressSnapshot {
            objects_discovered: self.objects_discovered.load(Ordering::Relaxed),
            bytes_discovered: self.bytes_discovered.load(Ordering::Relaxed),
            objects_completed: self.objects_completed.load(Ordering::Relaxed),
            bytes_completed: self.bytes_completed.load(Ordering::Relaxed),
            objects_failed: self.objects_failed.load(Ordering::Relaxed),
            objects_skipped: self.objects_skipped.load(Ordering::Relaxed),
            current_concurrent: self.current_concurrent.load(Ordering::Relaxed),
        }
    }
}

/// A point-in-time snapshot of progress counters.
#[derive(Debug, Clone, serde::Serialize)]
pub struct ProgressSnapshot {
    pub objects_discovered: u64,
    pub bytes_discovered: u64,
    pub objects_completed: u64,
    pub bytes_completed: u64,
    pub objects_failed: u64,
    pub objects_skipped: u64,
    pub current_concurrent: u32,
}

/// Trait for progress output backends.
pub trait ProgressReporter: Send + Sync + 'static {
    /// Called when the reporter should update its display.
    fn tick(&self, state: &ProgressState);
    /// Called when the entire session is complete.
    fn finish(&self, manifest: &CopyManifest);
}
