use std::collections::HashMap;

use crate::status::Status;

pub(crate) fn calculate_status(
    before: &HashMap<String, String>,
    after: &HashMap<String, String>,
) -> Status {
    let after_count = after.len();
    let before_count = before.len();

    if before_count > after_count {
        return Status::changed(
            format!("{before_count} present"),
            format!(
                "{} present, {} uninstalled",
                after_count,
                before_count - after_count
            ),
        );
    }

    let diff = after
        .iter()
        .filter(|(name, version)| before.get(name.as_str()) != Some(version))
        .count();

    if diff == 0 {
        Status::no_change(format!("{before_count} present, 0 installed"))
    } else {
        Status::changed(
            format!("{before_count} present"),
            format!("{before_count} present, {diff} installed"),
        )
    }
}

#[cfg(test)]
mod test {
    use crate::status::Satisfying;

    use super::*;

    #[test]
    fn nochange_for_same_versions() {
        let mut found: HashMap<String, String> = HashMap::new();
        found.insert(String::from("hello"), String::from("0.1.2"));
        found.insert(String::from("world"), String::from("1.2.3"));

        let got = calculate_status(&found, &found);
        assert_eq!(
            got,
            Status::Satisfying(Satisfying::NoChange(String::from("2 present, 0 installed")))
        );
    }

    #[test]
    fn changed_for_different_versions() {
        let mut before: HashMap<String, String> = HashMap::new();
        before.insert(String::from("hello"), String::from("0.1.2"));
        before.insert(String::from("world"), String::from("1.2.3"));

        let mut after = before.clone();
        after.insert(String::from("world"), String::from("2.3.4"));

        let got = calculate_status(&before, &after);
        assert_eq!(
            got,
            Status::Satisfying(Satisfying::Changed(
                String::from("2 present"),
                String::from("2 present, 1 installed")
            ))
        );
    }
}
