use crate::domain::model::decision_record::DecisionRecord;
use crate::domain::model::record_ref::DecisionRecordRef;
use crate::domain::usecases::issue::resolve::split_for_prefix_match;
use crate::domain::usecases::issue::Resolved;
use super::repository::DecisionRecordRepository;
pub fn find_decision_record_by_id_or_alias(
repo: &dyn DecisionRecordRepository,
raw: &str,
) -> anyhow::Result<Option<DecisionRecord>> {
match resolve_decision_record(repo, raw)? {
Resolved::Found(record) => Ok(Some(record)),
Resolved::NotFound | Resolved::AmbiguousPrefix { .. } => Ok(None),
}
}
pub fn resolve_decision_record(
repo: &dyn DecisionRecordRepository,
raw: &str,
) -> anyhow::Result<Resolved<DecisionRecord>> {
if let Ok(id) = raw.parse::<DecisionRecordRef>() {
if let Some(found) = repo.find_by_id(&id)? {
return Ok(Resolved::Found(found));
}
}
let records = repo.list()?;
if let Some((prefix, suffix)) = split_for_prefix_match(raw) {
if suffix.len() >= 3 {
let needle = format!("{prefix}-{}", suffix.to_ascii_uppercase());
let mut hits = Vec::new();
let mut hit_records = Vec::new();
for record in &records {
let id_str = record.id.as_str();
if id_str.len() != needle.len() && id_str.to_ascii_uppercase().starts_with(&needle)
{
hits.push(id_str.to_string());
hit_records.push(record.clone());
}
}
match hits.len() {
0 => {}
1 => return Ok(Resolved::Found(hit_records.into_iter().next().unwrap())),
_ => return Ok(Resolved::AmbiguousPrefix { matches: hits }),
}
}
}
for record in records {
if record.aliases.iter().any(|a| a == raw) {
return Ok(Resolved::Found(record));
}
}
Ok(Resolved::NotFound)
}