use std::collections::HashSet;
use regex::Regex;
use crate::contracts::Task;
use super::context::{TemplateValidation, TemplateWarning};
const KNOWN_VARIABLES: &[&str] = &["target", "module", "file", "branch"];
pub(super) fn extract_variables(input: &str) -> HashSet<String> {
let mut variables = HashSet::new();
let re = match Regex::new(r"\{\{(\w+)\}\}") {
Ok(re) => re,
Err(_) => return variables, };
for cap in re.captures_iter(input) {
if let Some(matched) = cap.get(1) {
variables.insert(matched.as_str().to_string());
}
}
variables
}
pub(super) fn uses_branch_variable(input: &str) -> bool {
input.contains("{{branch}}")
}
pub fn validate_task_template(task: &Task) -> TemplateValidation {
let mut validation = TemplateValidation::default();
let mut all_variables: HashSet<String> = HashSet::new();
let fields = [
("title", task.title.clone()),
("request", task.request.clone().unwrap_or_default()),
];
for (field_name, value) in &fields {
if uses_branch_variable(value) {
validation.uses_branch = true;
}
let vars = extract_variables(value);
for var in &vars {
if !KNOWN_VARIABLES.contains(&var.as_str()) {
validation.warnings.push(TemplateWarning::UnknownVariable {
name: var.clone(),
field: Some(field_name.to_string()),
});
}
all_variables.insert(var.clone());
}
}
let array_fields: [(&str, &[String]); 5] = [
("tags", &task.tags),
("scope", &task.scope),
("evidence", &task.evidence),
("plan", &task.plan),
("notes", &task.notes),
];
for (field_name, values) in &array_fields {
for value in *values {
if uses_branch_variable(value) {
validation.uses_branch = true;
}
let vars = extract_variables(value);
for var in &vars {
if !KNOWN_VARIABLES.contains(&var.as_str()) {
validation.warnings.push(TemplateWarning::UnknownVariable {
name: var.clone(),
field: Some(field_name.to_string()),
});
}
all_variables.insert(var.clone());
}
}
}
validation
}