use crate::replay::AcpReplay;
use std::path::{Path, PathBuf};

/// Load an ACP replay fixture by filename from the `fixtures/` directory.
pub fn load_fixture(name: &str) -> Result<AcpReplay, FixtureError> {
    let path = fixture_path(name);
    let content = std::fs::read_to_string(&path).map_err(|e| FixtureError::ReadError {
        path: path.clone(),
        source: e,
    })?;
    serde_json::from_str(&content).map_err(|e| FixtureError::ParseError { path, source: e })
}

/// Return the absolute path to a fixture file by name.
pub fn fixture_path(name: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("fixtures")
        .join(name)
}

/// List all `.json` fixture filenames in the `fixtures/` directory.
pub fn list_fixtures() -> Vec<String> {
    let fixtures_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("fixtures");
    std::fs::read_dir(fixtures_dir)
        .into_iter()
        .flatten()
        .filter_map(|e| e.ok())
        .filter(|e| e.path().extension().is_some_and(|ext| ext == "json"))
        .filter_map(|e| e.file_name().into_string().ok())
        .collect()
}

/// Errors that can occur when loading fixture files.
#[derive(Debug, thiserror::Error)]
pub enum FixtureError {
    #[error("Failed to read fixture at {path}: {source}")]
    ReadError {
        path: PathBuf,
        source: std::io::Error,
    },
    #[error("Failed to parse fixture at {path}: {source}")]
    ParseError {
        path: PathBuf,
        source: serde_json::Error,
    },
}
