use super::types::{BrokenLink, ErrorDoc};
use std::collections::{HashMap, HashSet};
use std::string::{String, ToString};
use std::vec::Vec;
pub fn validate_see_also_links(errors: &HashMap<String, ErrorDoc>) -> Vec<BrokenLink> {
let valid_codes: HashSet<&str> = errors.values().map(|e| e.code.as_str()).collect();
let mut broken_links = Vec::new();
for error in errors.values() {
for (referenced, _role) in &error.see_also_gated {
if !valid_codes.contains(referenced.as_str()) {
let prefix_len = referenced.len().min(10);
let prefix = &referenced[..prefix_len];
let suggestions: Vec<String> = valid_codes
.iter()
.filter(|code| code.starts_with(prefix) || is_similar(code, referenced))
.take(5)
.map(|s| s.to_string())
.collect();
broken_links.push(
BrokenLink::new(error.code.clone(), referenced.clone())
.with_suggestions(suggestions),
);
}
}
}
broken_links
}
fn is_similar(code: &str, target: &str) -> bool {
let code_parts: Vec<&str> = code.split('.').collect();
let target_parts: Vec<&str> = target.split('.').collect();
if code_parts.len() >= 3 && target_parts.len() >= 3 {
code_parts[0] == target_parts[0]
&& code_parts[1] == target_parts[1]
&& code_parts[2] == target_parts[2]
} else {
false
}
}