use std::{
	env,
	fmt::Write as _,
	fs,
	path::{Path, PathBuf},
};

fn main() {
	generate_minimizer_builtin_filters();
}

fn generate_minimizer_builtin_filters() {
	let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should be set");
	let defs_dir = Path::new(&manifest_dir)
		.join("src")
		.join("minimizer")
		.join("defs");
	let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR should be set"));
	let output_path = out_dir.join("builtin_filters.toml");

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

	let mut concatenated =
		String::from("# Auto-generated by build.rs -- do not edit.\nschema_version = 1\n\n");

	let mut entries: Vec<PathBuf> = Vec::new();
	if let Ok(read_dir) = fs::read_dir(&defs_dir) {
		for entry in read_dir.flatten() {
			let path = entry.path();
			if path.extension().and_then(|extension| extension.to_str()) == Some("toml") {
				entries.push(path);
			}
		}
	}
	entries.sort();

	for path in entries {
		println!("cargo:rerun-if-changed={}", path.display());
		match fs::read_to_string(&path) {
			Ok(body) => {
				let filename = path
					.file_name()
					.and_then(|name| name.to_str())
					.unwrap_or("unknown");
				writeln!(concatenated, "# --- {filename} ---").expect("write to String");
				for line in body.lines() {
					let trimmed = line.trim_start();
					if trimmed.starts_with("schema_version") {
						continue;
					}
					concatenated.push_str(line);
					concatenated.push('\n');
				}
				concatenated.push('\n');
			},
			Err(error) => panic!("failed to read filter definition {}: {error}", path.display()),
		}
	}

	fs::write(&output_path, concatenated)
		.unwrap_or_else(|error| panic!("failed to write {}: {error}", output_path.display()));
}