//! Human-readable terminal progress reporting using `indicatif`.

#[cfg(feature = "cli")]
use indicatif::{ProgressBar, ProgressStyle};

#[cfg(feature = "cli")]
use crate::progress::reporter::{ProgressReporter, ProgressState};
#[cfg(feature = "cli")]
use crate::types::CopyManifest;

/// Terminal progress bar reporter.
#[cfg(feature = "cli")]
pub struct HumanReporter {
    bar: ProgressBar,
}

#[cfg(feature = "cli")]
impl Default for HumanReporter {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(feature = "cli")]
impl HumanReporter {
    /// Create a new progress bar with a spinner style.
    pub fn new() -> Self {
        let bar = ProgressBar::new_spinner();
        bar.set_style(
            ProgressStyle::default_spinner()
                .template("{spinner:.green} [{elapsed_precise}] {msg}")
                .unwrap(),
        );
        bar.enable_steady_tick(std::time::Duration::from_millis(200));
        Self { bar }
    }
}

#[cfg(feature = "cli")]
impl ProgressReporter for HumanReporter {
    fn tick(&self, state: &ProgressState) {
        let snap = state.snapshot();
        let bytes_str = humansize::format_size(snap.bytes_completed, humansize::BINARY);
        self.bar.set_message(format!(
            "{}/{} objects | {} copied | {} failed",
            snap.objects_completed, snap.objects_discovered, bytes_str, snap.objects_failed,
        ));
    }

    fn finish(&self, manifest: &CopyManifest) {
        let bytes_str = humansize::format_size(manifest.copied_bytes, humansize::BINARY);
        self.bar.finish_with_message(format!(
            "Done: {} copied, {} skipped, {} failed | {} in {:.1}s",
            manifest.copied_objects,
            manifest.skipped_objects,
            manifest.failed_objects,
            bytes_str,
            manifest.duration_secs,
        ));
    }
}
