//! ```text
//! NAME
//!         stale-label
//!
//! SYNOPSIS
//!         stale-label
//!
//! DESCRIPTION
//!         Detect stale paths in autolabel definitions in triagebot.toml.
//!         Probably autofix them in the future.
//! ```

#![allow(clippy::print_stderr)]

use std::fmt::Write as _;
use std::path::PathBuf;
use std::process;
use toml_edit::DocumentMut;

fn main() {
    let pkg_root = std::env!("CARGO_MANIFEST_DIR");
    let ws_root = PathBuf::from(format!("{pkg_root}/../.."));
    let path = {
        let path = ws_root.join("triagebot.toml");
        path.canonicalize().unwrap_or(path)
    };

    eprintln!("Checking file {path:?}\n");

    let mut failed = 0;
    let mut passed = 0;

    let toml = std::fs::read_to_string(path).expect("read from file");
    let doc = toml.parse::<DocumentMut>().expect("a toml");
    let autolabel = doc["autolabel"].as_table().expect("a toml table");

    for (label, value) in autolabel.iter() {
        let Some(trigger_files) = value.get("trigger_files") else {
            continue;
        };
        let trigger_files = trigger_files.as_array().expect("an array");
        let missing_files: Vec<_> = trigger_files
            .iter()
            // Hey TOML content is strict UTF-8.
            .map(|v| v.as_str().unwrap())
            .filter(|f| {
                // triagebot checks with `starts_with` only.
                // See https://github.com/rust-lang/triagebot/blob/0e4b48ca86ffede9cc70fb1611e658e4d013bce2/src/handlers/autolabel.rs#L45
                let path = ws_root.join(f);
                if path.exists() {
                    return false;
                }
                let Some(mut read_dir) = path.parent().and_then(|p| p.read_dir().ok()) else {
                    return true;
                };
                !read_dir.any(|e| {
                    e.unwrap()
                        .path()
                        .strip_prefix(&ws_root)
                        .unwrap()
                        .to_str()
                        .unwrap()
                        .starts_with(f)
                })
            })
            .collect();

        failed += missing_files.len();
        passed += trigger_files.len() - missing_files.len();

        if missing_files.is_empty() {
            continue;
        }

        let mut msg = String::new();
        writeln!(
            &mut msg,
            "missing files defined in `autolabel.{label}.trigger_files`:"
        )
        .unwrap();
        for f in missing_files.iter() {
            writeln!(&mut msg, "\t {f}").unwrap();
        }
        eprintln!("{msg}");
    }

    let result = if failed == 0 { "ok" } else { "FAILED" };
    eprintln!("test result: {result}. {passed} passed; {failed} failed;");

    if failed > 0 {
        process::exit(1);
    }
}
