use std::{fs, path::Path, process::Command};

use crate::io::print_items;

fn diff_type(
    folder: &str,
    from_version: &str,
    to_version: &str,
) -> Result<Option<()>, Box<dyn std::error::Error>> {
    let old_ini = format!("/etc/php/{}/{}/php.ini", from_version, folder);
    let old_exists = Path::new(&old_ini).exists();

    if !old_exists {
        return Ok(None);
    }

    println!("\nphp.ini diff for {}:", folder);

    let new_ini = format!("/etc/php/{}/{}/php.ini", to_version, folder);
    let new_exists = Path::new(&new_ini).exists();

    if !new_exists {
        println!("REMOVED");
        return Ok(Some(()));
    }

    Command::new("diff")
        .arg("--color")
        .arg(old_ini)
        .arg(new_ini)
        .status()?;

    Ok(Some(()))
}

pub fn show_ini_diff(
    from_version: &str,
    to_version: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    let paths = fs::read_dir(format!("/etc/php/{}", from_version)).map_err(|_| {
        format!(
            "Could not find /etc/php/{} to show ini diffs.",
            from_version
        )
    })?;

    let shown: Vec<String> = paths
        .filter_map(|res| {
            let folder = res
                .map_err(|e| println!("Could not read directory entry: {}", e))
                .ok()?
                .file_name()
                .to_string_lossy()
                .to_string();

            diff_type(&folder, from_version, to_version)
                .map_err(|_| println!("Could not run diff for {}", folder))
                .ok()?
                .map(|_| folder)
        })
        .collect();

    print!("\nShowed diff files for: ");
    print_items(shown);

    Ok(())
}
