//! Baseline and diff operations for tracking changes over time.

use crate::config::AphoriaConfig;
use crate::error::AphoriaError;
use crate::scan::{generate_scan_id, run_scan};
use crate::types::{ScanArgs, ScanMode, Verdict};
use tracing::{info, instrument};

/// Set the current scan as the baseline.
///
/// Future `aphoria diff` commands will compare against this baseline.
#[instrument(skip(_config))]
pub async fn set_baseline(_config: &AphoriaConfig) -> Result<(), AphoriaError> {
    info!("Setting baseline");

    let project_root = std::env::current_dir()?;
    let aphoria_dir = project_root.join(".aphoria");
    std::fs::create_dir_all(&aphoria_dir)?;

    // Record the current scan ID as baseline
    let scan_id = generate_scan_id();
    std::fs::write(aphoria_dir.join("baseline"), &scan_id)?;

    info!(scan_id, "Baseline set");
    Ok(())
}

/// Show changes since the last baseline.
#[instrument(skip(config))]
pub async fn show_diff(config: &AphoriaConfig) -> Result<String, AphoriaError> {
    info!("Showing diff");

    let project_root = std::env::current_dir()?;
    let baseline_path = project_root.join(".aphoria").join("baseline");

    if !baseline_path.exists() {
        return Err(AphoriaError::NoBaseline);
    }

    // For now, just run a scan and compare against baseline
    // Full diff implementation would track assertion hashes
    // Diff needs persistent mode to access stored claims
    let args = ScanArgs {
        path: project_root,
        format: "table".to_string(),
        exit_code_enabled: false,
        mode: ScanMode::Persistent,
        debug: false,
        sync: false, // Diff does not write observations
        file_source: crate::types::FileSource::All,
        benchmark: false,
        show_claims: false,
    };

    let result = run_scan(args, config).await?;

    let mut output = String::new();
    output.push_str("Changes since baseline:\n\n");
    output.push_str(&format!(
        "  {} conflicts ({} BLOCK, {} FLAG)\n",
        result.conflicts.len(),
        result.count_by_verdict(Verdict::Block),
        result.count_by_verdict(Verdict::Flag),
    ));

    Ok(output)
}
