use sha2::{Digest, Sha256};

pub fn compute_fingerprint(parts: &[&str]) -> String {
    let mut hasher = Sha256::new();
    for part in parts {
        hasher.update(part.as_bytes());
        hasher.update(b"|");
    }
    hex::encode(hasher.finalize())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn fingerprint_is_deterministic() {
        let a = compute_fingerprint(&["repo1", "rule-x", "src/main.rs", "42"]);
        let b = compute_fingerprint(&["repo1", "rule-x", "src/main.rs", "42"]);
        assert_eq!(a, b);
    }

    #[test]
    fn fingerprint_changes_with_different_input() {
        let a = compute_fingerprint(&["repo1", "rule-x", "src/main.rs", "42"]);
        let b = compute_fingerprint(&["repo1", "rule-x", "src/main.rs", "43"]);
        assert_ne!(a, b);
    }

    #[test]
    fn fingerprint_is_valid_hex_sha256() {
        let fp = compute_fingerprint(&["hello"]);
        assert_eq!(fp.len(), 64, "SHA-256 hex should be 64 chars");
        assert!(fp.chars().all(|c| c.is_ascii_hexdigit()));
    }

    #[test]
    fn fingerprint_empty_parts() {
        let fp = compute_fingerprint(&[]);
        // Should still produce a valid hash (of empty input)
        assert_eq!(fp.len(), 64);
    }

    #[test]
    fn fingerprint_order_matters() {
        let a = compute_fingerprint(&["a", "b"]);
        let b = compute_fingerprint(&["b", "a"]);
        assert_ne!(a, b);
    }

    #[test]
    fn fingerprint_separator_prevents_collision() {
        // "ab" + "c" vs "a" + "bc" should differ because of the "|" separator
        let a = compute_fingerprint(&["ab", "c"]);
        let b = compute_fingerprint(&["a", "bc"]);
        assert_ne!(a, b);
    }
}
