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_content/
    // Workspace root is 4 ancestors up.
    let crate_path = Path::new(&manifest_dir);
    let workspace_root = crate_path
        .ancestors()
        .nth(4)
        .expect("workspace root must be 4 levels above crate");

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

    // Rerun when resources change
    println!("cargo:rerun-if-changed={}", resources_i18n.display());

    generate_content_ftl(&resources_i18n, &out_dir);
}

/// Generates `content_ftl.rs` — a `get_content_ftl()` function returning
/// `HashMap<&'static str, &'static str>` keyed by `"{lang}_{file_stem}"`.
///
/// Only embeds files from `pages/content.ftl`, `pages/post.ftl`, and
/// `features/` subdirectory — the content-specific FTL strings.
fn generate_content_ftl(resources_i18n: &Path, out_dir: &str) {
    let mut code = String::from(
        "// Auto-generated by rustelo_content build.rs — DO NOT EDIT.\npub fn get_content_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("content_ftl.rs"), code).expect("write content_ftl.rs");
        return;
    }

    let target_files = ["pages/content.ftl", "pages/post.ftl"];

    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 lang_dir = lang_entry.path();

        for rel in &target_files {
            let full = lang_dir.join(rel);
            if full.exists() {
                let stem = Path::new(rel)
                    .file_stem()
                    .unwrap_or_default()
                    .to_string_lossy();
                let key = format!("{}_{}", lang, stem);
                code.push_str(&format!(
                    "m.insert(\"{key}\", include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \
                     \"/../../../../resources/i18n/{lang}/{rel}\")));\n",
                    key = key,
                    lang = lang,
                    rel = rel,
                ));
            }
        }

        // Also embed features/ FTL if present
        let features_dir = lang_dir.join("features");
        if features_dir.exists() {
            for feat_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)
                })
            {
                let stem = feat_entry
                    .path()
                    .file_stem()
                    .unwrap_or_default()
                    .to_string_lossy()
                    .to_string();
                let rel_feat = format!("features/{}", feat_entry.file_name().to_string_lossy());
                let key = format!("{}_{}", lang, stem);
                code.push_str(&format!(
                    "m.insert(\"{key}\", include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \
                     \"/../../../../resources/i18n/{lang}/{rel_feat}\")));\n",
                    key = key,
                    lang = lang,
                    rel_feat = rel_feat,
                ));
            }
        }
    }

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