use std::{
    env, fs,
    io::{BufRead, BufReader, Write as IoWrite},
    path::PathBuf,
};

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=data/cities1000.txt");

    let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    let cities_txt   = manifest_dir.join("data").join("cities1000.txt");
    let out_dir      = env::var("OUT_DIR").unwrap();

    if cities_txt.exists() {
        generate(&cities_txt, &out_dir);
    } else {
        eprintln!("cargo:warning=core/data/cities1000.txt not found — city search will be empty.");
        write_empty(&out_dir);
    }
}

fn generate(cities_txt: &PathBuf, out_dir: &str) {
    let reader = BufReader::new(fs::File::open(cities_txt).unwrap());
    let mut cities: Vec<(String, String, String, f32, f32)> = Vec::new();

    for line in reader.lines() {
        let line = line.unwrap();
        let f: Vec<&str> = line.splitn(20, '\t').collect();
        if f.len() < 9 { continue; }
        let ascii = f[2];
        if ascii.is_empty() { continue; }
        let lat: f32 = match f[4].parse() { Ok(v) => v, Err(_) => continue };
        let lon: f32 = match f[5].parse() { Ok(v) => v, Err(_) => continue };
        let cc = f[8];
        cities.push((ascii.to_lowercase(), ascii.to_string(), cc.to_string(), lat, lon));
    }

    cities.sort_unstable_by(|a, b| a.0.cmp(&b.0));

    let out_path = PathBuf::from(out_dir).join("cities_data.rs");
    let mut out = fs::File::create(&out_path).unwrap();
    writeln!(out, "// Auto-generated by build.rs from GeoNames cities1000.txt — do not edit.").unwrap();
    writeln!(out, "static CITIES: &[(&str, &str, &str, f32, f32)] = &[").unwrap();
    for (lower, name, cc, lat, lon) in &cities {
        let lower = lower.replace('"', "\\\"");
        let name  = name .replace('"', "\\\"");
        let cc    = cc   .replace('"', "\\\"");
        writeln!(out, "    (\"{lower}\",\"{name}\",\"{cc}\",{lat:.4}f32,{lon:.4}f32),").unwrap();
    }
    writeln!(out, "];").unwrap();
}

fn write_empty(out_dir: &str) {
    let out_path = PathBuf::from(out_dir).join("cities_data.rs");
    fs::write(out_path,
        "// cities1000.txt not found — empty fallback.\n\
         static CITIES: &[(&str, &str, &str, f32, f32)] = &[];\n",
    ).unwrap();
}
