use std::path::Path;

use crate::app::helpers::state_io::{
    export_runtime_overlay_import_document, export_runtime_save_slice_document,
};
use crate::app::reports::state::RuntimeStateSummaryReport;
use rrt_runtime::{
    documents::build_runtime_state_input_from_save_slice,
    inspect::smp::save_load::load_save_slice_file,
    persistence::{
        RuntimeSnapshotDocument, RuntimeSnapshotSource, SNAPSHOT_FORMAT_VERSION,
        save_runtime_snapshot_document,
    },
};

pub(crate) fn snapshot_save_state(
    smp_path: &Path,
    output_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
    let save_slice = load_save_slice_file(smp_path)?;
    let input = build_runtime_state_input_from_save_slice(
        &save_slice,
        smp_path
            .file_stem()
            .and_then(|stem| stem.to_str())
            .unwrap_or("save-state"),
        Some(format!(
            "Projected partial runtime state from save {}",
            smp_path.display()
        )),
    )
    .map_err(|err| format!("failed to project save slice: {err}"))?;
    let snapshot = RuntimeSnapshotDocument {
        format_version: SNAPSHOT_FORMAT_VERSION,
        snapshot_id: format!("{}-snapshot", input.input_id),
        source: RuntimeSnapshotSource {
            source_fixture_id: None,
            description: input.description,
        },
        state: input.state,
    };
    save_runtime_snapshot_document(output_path, &snapshot)?;
    let report = RuntimeStateSummaryReport {
        snapshot_id: snapshot.snapshot_id.clone(),
        summary: snapshot.summary(),
    };
    println!("{}", serde_json::to_string_pretty(&report)?);
    Ok(())
}

pub(crate) fn export_save_slice(
    smp_path: &Path,
    output_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
    let save_slice = load_save_slice_file(smp_path)?;
    let report = export_runtime_save_slice_document(smp_path, output_path, save_slice)?;
    println!("{}", serde_json::to_string_pretty(&report)?);
    Ok(())
}

pub(crate) fn export_overlay_import(
    snapshot_path: &Path,
    save_slice_path: &Path,
    output_path: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
    let report =
        export_runtime_overlay_import_document(snapshot_path, save_slice_path, output_path)?;
    println!("{}", serde_json::to_string_pretty(&report)?);
    Ok(())
}
