use std::io::Write;
use std::path::PathBuf;
use crate::finding::{Category, Finding};
pub(crate) fn run_doctor(path: Option<PathBuf>, json: bool) -> anyhow::Result<()> {
let root = crate::root::find(path, &crate::root::default_markers())?;
let mut findings: Vec<Finding> = Vec::new();
findings.extend(crate::integrity::id_integrity_findings_native(&root)?);
let rel_lines = crate::relation_graph::validate_relations(&root)?;
findings.extend(Finding::from_lines(Category::RelationIntegrity, rel_lines));
let fk_lines = crate::spec::spec_fk_findings(&root);
findings.extend(Finding::from_lines(Category::SpecFk, fk_lines));
let today = crate::clock::today();
let mem_findings = match crate::memory::collect_memories(&root) {
Ok(memories) => crate::memory::memory_health_findings_native(&root, &memories, &today),
Err(_) => Vec::new(),
};
findings.extend(mem_findings);
findings.extend(crate::backlog::lifecycle_findings(&root));
findings.extend(crate::doctor_checks::raw_label_findings(&root));
findings.extend(crate::doctor_checks::toml_parse_findings(&root));
findings.extend(crate::doctor_checks::prose_cite_findings(&root));
if json {
let json_out = crate::listing::json_envelope("doctor", &findings)?;
writeln!(std::io::stdout(), "{json_out}")?;
} else {
let rendered = crate::finding::render_findings(&findings);
writeln!(std::io::stdout(), "{rendered}")?;
}
let has_errors = findings
.iter()
.any(|f| f.category.severity() == crate::finding::Severity::Error);
if has_errors {
anyhow::bail!("{} finding(s)", findings.len());
}
Ok(())
}