use std::path::{Path, PathBuf};
use anyhow::{Result};
use serde::{Serialize, Deserialize};
use std::fs;
use chrono::{DateTime, Utc};
use crate::core::detection::scanner::Scanner;
use crate::core::registry::RecipeRegistry;
use crate::core::pipeline::executor::{PipelineExecutor};
use crate::core::recipe::TransformMode;
use crate::utils::terminal;
use crate::commands::verify::run_verification;
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidationRepoReport {
pub timestamp: DateTime<Utc>,
pub target_path: PathBuf,
pub total_files: usize,
pub recipes_detected: usize,
pub dry_run_modifications: usize,
pub verification_errors: usize,
pub verification_warnings: usize,
}
pub fn execute(path: &Path, project_root: &Path) -> Result<()> {
let spinner = terminal::spinner(format!("Validating repository: {}...", path.display()).as_str());
let mut scanner = Scanner::new(path.to_path_buf());
let _scan_result = scanner.scan();
let mut total_files = 0;
for entry in walkdir::WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
if entry.file_type().is_file() {
total_files += 1;
}
}
let registry = RecipeRegistry::new();
let mut recipes_detected = 0;
for recipe in registry.all() {
if let Ok(report) = recipe.detect(path, &indicatif::ProgressBar::hidden()) {
if !report.analyses.is_empty() {
recipes_detected += 1;
}
}
}
let mut executor = PipelineExecutor::new(path.to_path_buf());
for recipe in registry.all() {
executor = executor.add_recipe(recipe.metadata().name);
}
let pipeline_summary = executor.execute(
path,
TransformMode::DryRun,
false, false, ®istry,
false )?;
let verify_summary = run_verification(path)?;
spinner.finish_and_clear();
let report = ValidationRepoReport {
timestamp: Utc::now(),
target_path: path.to_path_buf(),
total_files,
recipes_detected,
dry_run_modifications: pipeline_summary.total_changed_files,
verification_errors: verify_summary.total_errors,
verification_warnings: verify_summary.total_warnings,
};
let validation_dir = project_root.join(".morph-cli/validation");
fs::create_dir_all(&validation_dir)?;
let report_path = validation_dir.join(format!("validation_{}.json", report.timestamp.timestamp()));
let json = serde_json::to_string_pretty(&report)?;
fs::write(&report_path, json)?;
println!();
println!("{} Repository Validation Summary", terminal::label("─".repeat(50).as_str()));
println!(" Target Path: {}", path.display());
println!(" Total Files: {}", report.total_files);
println!(" Recipes Active:{}", report.recipes_detected);
println!(" Dry-run Mods: {}", report.dry_run_modifications);
println!(" Baseline Errs: {}", report.verification_errors);
println!(" Baseline Warns:{}", report.verification_warnings);
println!(" Report Stored: {}", report_path.display());
println!();
Ok(())
}