use std::{env, fs, path::Path};

use walkdir::WalkDir;

fn main() {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR set by cargo");
    let out_dir = env::var("OUT_DIR").expect("OUT_DIR set by cargo");

    // Crate is at: rustelo/crates/framework/crates/rustelo_auth/
    // Workspace root is 4 ancestors up.
    let workspace_root = Path::new(&manifest_dir)
        .ancestors()
        .nth(4)
        .expect("workspace root must be 4 levels above crate");

    let resources_i18n = workspace_root.join("resources").join("i18n");

    println!("cargo:rerun-if-changed={}", resources_i18n.display());

    generate_auth_ftl(&resources_i18n, &out_dir);
}

/// Generates `auth_ftl.rs` — a `get_auth_ftl()` function returning
/// `HashMap<&'static str, &'static str>` keyed by `"{lang}_{file_stem}"`.
///
/// Only embeds files from `features/auth.ftl` and `features/auth-signout.ftl`.
fn generate_auth_ftl(resources_i18n: &Path, out_dir: &str) {
    let mut code = String::from(
        "// Auto-generated by rustelo_auth build.rs — DO NOT EDIT.\npub fn get_auth_ftl() -> \
         std::collections::HashMap<&'static str, &'static str> {\nlet mut m = \
         std::collections::HashMap::new();\n",
    );

    if !resources_i18n.exists() {
        code.push_str("m\n}\n");
        fs::write(Path::new(out_dir).join("auth_ftl.rs"), code).expect("write auth_ftl.rs");
        return;
    }

    for lang_entry in WalkDir::new(resources_i18n)
        .max_depth(1)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| e.file_type().is_dir() && e.depth() == 1)
    {
        let lang = lang_entry.file_name().to_string_lossy().to_string();
        let features_dir = lang_entry.path().join("features");

        if !features_dir.exists() {
            continue;
        }

        for entry in WalkDir::new(&features_dir)
            .max_depth(1)
            .into_iter()
            .filter_map(|e| e.ok())
            .filter(|e| {
                e.file_type().is_file()
                    && e.path().extension().map(|x| x == "ftl").unwrap_or(false)
                    && e.path()
                        .file_stem()
                        .and_then(|s| s.to_str())
                        .map(|s| s == "auth" || s == "auth-signout")
                        .unwrap_or(false)
            })
        {
            let stem = entry
                .path()
                .file_stem()
                .unwrap_or_default()
                .to_string_lossy()
                // auth-signout → auth_signout (hyphens → underscores for valid Rust key)
                .replace('-', "_");
            let file_name = entry.file_name().to_string_lossy().to_string();
            let key = format!("{}_{}", lang, stem);

            code.push_str(&format!(
                "m.insert(\"{key}\", include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \
                 \"/../../../../resources/i18n/{lang}/features/{file_name}\")));\n",
                key = key,
                lang = lang,
                file_name = file_name,
            ));
        }
    }

    code.push_str("m\n}\n");
    fs::write(Path::new(out_dir).join("auth_ftl.rs"), &code).expect("write auth_ftl.rs");
}
