use rustc_hash::FxHashMap;
use rustledger_core::{Document, Note};
use std::path::Path;
use crate::LedgerState;
use crate::error::{ErrorCode, ValidationError};
pub fn validate_note(state: &LedgerState, note: &Note, errors: &mut Vec<ValidationError>) {
if !state.accounts.contains_key(¬e.account) {
errors.push(ValidationError::new(
ErrorCode::AccountNotOpen,
format!("Invalid reference to unknown account '{}'", note.account),
note.date,
));
}
}
pub fn validate_document(
state: &LedgerState,
doc: &Document,
exists_cache: &FxHashMap<String, bool>,
errors: &mut Vec<ValidationError>,
) {
if !state.accounts.contains_key(&doc.account) {
errors.push(ValidationError::new(
ErrorCode::AccountNotOpen,
format!("Invalid reference to unknown account '{}'", doc.account),
doc.date,
));
}
if state.options.check_documents {
let file_was_found = exists_cache.get(&doc.path).copied().unwrap_or_else(|| {
debug_assert!(
false,
"Document path `{}` missing from pre-resolved exists_cache — \
build_document_exists_cache enumeration must match this validator's resolution",
doc.path
);
let doc_path = Path::new(&doc.path);
if doc_path.is_absolute() {
doc_path.exists()
} else if let Some(base) = &state.options.document_base {
base.join(doc_path).exists()
} else if !state.options.document_dirs.is_empty() {
state
.options
.document_dirs
.iter()
.any(|dir| dir.join(doc_path).exists())
} else {
doc_path.exists()
}
});
if !file_was_found {
let doc_path = Path::new(&doc.path);
let mut error = ValidationError::new(
ErrorCode::DocumentNotFound,
format!("Document file not found: {}", doc.path),
doc.date,
);
if doc_path.is_relative()
&& state.options.document_base.is_none()
&& !state.options.document_dirs.is_empty()
{
let searched: Vec<String> = state
.options
.document_dirs
.iter()
.map(|d| d.join(doc_path).display().to_string())
.collect();
error = error.with_context(format!("searched: {}", searched.join(", ")));
} else {
let resolved = if doc_path.is_absolute() {
doc_path.to_path_buf()
} else if let Some(base) = &state.options.document_base {
base.join(doc_path)
} else {
doc_path.to_path_buf()
};
error = error.with_context(format!("resolved path: {}", resolved.display()));
}
errors.push(error);
}
}
}