// Implementations of Subplot scenario steps for wumpus.md.

use std::path::{Path, PathBuf};

use walkdir::WalkDir;

use subplotlib::steplibrary::{datadir::Datadir, runcmd::Runcmd};

#[derive(Debug, Default)]
struct SubplotContext {}

impl ContextElement for SubplotContext {}

#[step]
#[context(SubplotContext)]
#[context(Runcmd)]
fn install_wumpus(context: &ScenarioContext) {
    let target_exe = env!("CARGO_BIN_EXE_wumpus-hunter");
    let target_path = Path::new(target_exe);
    let target_path = target_path.parent().ok_or("No parent?")?;
    context.with_mut(
        |context: &mut Runcmd| {
            context.prepend_to_path(target_path);
            Ok(())
        },
        false,
    )?;
}

#[step]
#[context(SubplotContext)]
#[context(Datadir)]
fn count_results(context: &ScenarioContext, successful: usize, failed: usize, dirname: &Path) {
    context.with_mut(
        |context: &mut Datadir| {
            let dirname = context.canonicalise_filename(dirname)?;
            println!("cwd is {}", std::env::current_dir().expect("cwd").display());
            println!(
                "dirname: {} (exists? {})",
                dirname.display(),
                dirname.exists()
            );

            let files = listdir(&dirname);
            println!("files: {files:#?}");
            let found_successful = count(&files, "success.html");
            let found_failed = count(&files, "fail.html");

            println!("want successful {successful}, got {found_successful}");
            println!("want failed {failed}, got {found_failed}");

            assert_eq!(successful, found_successful);
            assert_eq!(failed, found_failed);
            Ok(())
        },
        false,
    )?;
}

fn listdir(dirname: &Path) -> Vec<PathBuf> {
    let mut files = vec![];
    for entry in WalkDir::new(dirname).min_depth(2).max_depth(2) {
        let entry = entry.unwrap();
        files.push(entry.path().into());
    }
    files
}

fn count(files: &[PathBuf], substring: &str) -> usize {
    files
        .iter()
        .filter_map(|path| {
            if format!("{}", path.display()).contains(substring) {
                Some(true)
            } else {
                None
            }
        })
        .count()
}
