//! Lazy preview cache for the picker.
//!
//! Each worktree's preview (recent commits + short diffstat) is computed
//! once on first highlight and held in-memory for the rest of the
//! session. The picker is interactive, so we eat the git hit once but
//! not on every keystroke.

use std::collections::HashMap;
use std::path::{Path, PathBuf};

use crate::git;

const LOG_LIMIT: usize = 8;
const DIFF_STAT_LIMIT: usize = 12;

/// One worktree's rendered preview content.
#[derive(Debug, Clone, Default)]
pub struct Preview {
    /// `git log --oneline` lines, most recent first (up to `LOG_LIMIT`).
    pub commits: Vec<String>,
    /// `git diff --stat` lines (up to `DIFF_STAT_LIMIT`).
    pub diff_stat: Vec<String>,
}

/// Per-worktree preview memoisation.
#[derive(Default)]
pub struct Cache {
    data: HashMap<PathBuf, Preview>,
}

impl Cache {
    /// Returns the preview for `wt_path`, computing and caching it on
    /// first call.
    pub fn get_or_compute(&mut self, wt_path: &Path) -> &Preview {
        self.data
            .entry(wt_path.to_path_buf())
            .or_insert_with(|| compute(wt_path))
    }
}

fn compute(path: &Path) -> Preview {
    let commits = git::capture(
        path,
        &[
            "log",
            "-n",
            &LOG_LIMIT.to_string(),
            "--oneline",
            "--decorate",
            "--color=never",
        ],
    )
    .map(|s| s.lines().map(String::from).collect())
    .unwrap_or_default();

    let diff_stat = git::capture(path, &["diff", "--stat", "--color=never"])
        .map(|s| s.lines().take(DIFF_STAT_LIMIT).map(String::from).collect())
        .unwrap_or_default();

    Preview { commits, diff_stat }
}
