wilayah 0.6.1

Location lookup for Indonesian villages by GPS coordinates or name
use rusqlite::Connection;
use serde_json::{json, Value};
use wilayah::builder::{ParseOutputDetail, Pipeline};

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let mut pipeline = Pipeline::new();
    let mut save_legacy_snapshot = false;
    let mut skip_big = false;

    if std::env::var("WILAYAH_REFRESH_BIG").as_deref() == Ok("1") {
        pipeline = pipeline.force_refresh_big(true);
    }

    let mut cache_dir = std::path::PathBuf::from("data/cache");
    let mut i = 1;
    while i < args.len() {
        match args[i].as_str() {
            "--output" | "-o" => {
                if i + 1 < args.len() {
                    pipeline = pipeline.output(std::path::Path::new(&args[i + 1]));
                    i += 2;
                } else {
                    eprintln!("error: --output requires a path");
                    std::process::exit(1);
                }
            }
            "--cache-dir" => {
                if i + 1 < args.len() {
                    cache_dir = std::path::PathBuf::from(&args[i + 1]);
                    pipeline = pipeline.cache_dir(&cache_dir);
                    i += 2;
                } else {
                    eprintln!("error: --cache-dir requires a path");
                    std::process::exit(1);
                }
            }
            "--pdf-url" => {
                if i + 1 < args.len() {
                    pipeline = pipeline.pdf_url(&args[i + 1]);
                    i += 2;
                } else {
                    eprintln!("error: --pdf-url requires a URL");
                    std::process::exit(1);
                }
            }
            "--big-api-url" => {
                if i + 1 < args.len() {
                    pipeline = pipeline.big_api_url(&args[i + 1]);
                    i += 2;
                } else {
                    eprintln!("error: --big-api-url requires a URL");
                    std::process::exit(1);
                }
            }
            "--force-refresh-big" => {
                pipeline = pipeline.force_refresh_big(true);
                i += 1;
            }
            "--skip-big" => {
                skip_big = true;
                i += 1;
            }
            "--save-legacy-snapshot" => {
                save_legacy_snapshot = true;
                i += 1;
            }
            "--include-polygons" => {
                pipeline = pipeline.include_polygons(true);
                i += 1;
            }
            "--save-parsed-villages" => {
                let detail = if i + 1 < args.len() && !args[i + 1].starts_with('-') {
                    let level = &args[i + 1];
                    i += 2;
                    match level.as_str() {
                        "minimal" => ParseOutputDetail::Minimal,
                        "raw" => ParseOutputDetail::WithRawName,
                        "full" => ParseOutputDetail::Full,
                        _ => {
                            eprintln!(
                                "error: unknown detail level '{level}' (use minimal, raw, or full)"
                            );
                            std::process::exit(1);
                        }
                    }
                } else {
                    i += 1;
                    ParseOutputDetail::Minimal
                };
                pipeline = pipeline.save_parsed_villages(detail);
            }
            _ => {
                eprintln!("warning: unknown argument: {}", args[i]);
                i += 1;
            }
        }
    }

    if skip_big {
        pipeline = pipeline
            .force_refresh_big(false)
            .big_api_url("http://127.0.0.1:9999/nonexistent");
    }

    match pipeline.run() {
        Ok(output) => {
            println!("Pipeline completed successfully.");
            println!("Database: {}", output.db_path.display());
            if let Some(poly) = &output.poly_db_path {
                println!("Polygon DB: {}", poly.display());
            }
            if let Some(parsed) = &output.parsed_villages_path {
                println!("Parsed villages: {}", parsed.display());
            }
            if let Some(dist) = &output.parsed_districts_path {
                println!("Parsed districts: {}", dist.display());
            }
            if let Some(prov) = &output.parsed_provinces_path {
                println!("Parsed provinces: {}", prov.display());
            }
            if let Some(city) = &output.parsed_cities_path {
                println!("Parsed cities: {}", city.display());
            }
            if let Some(sum) = &output.parsed_island_summaries_path {
                println!("Parsed island summaries: {}", sum.display());
            }
            if let Some(isl) = &output.parsed_islands_path {
                println!("Parsed islands: {}", isl.display());
            }
            println!("Villages: {}", output.village_count);
            println!("SHA-256: {}", output.sha256);

            if save_legacy_snapshot {
                if let Err(e) = save_legacy_snapshot_to(&output.db_path, &cache_dir) {
                    eprintln!("Failed to save legacy snapshot: {}", e);
                    std::process::exit(1);
                }
            }

            std::process::exit(0);
        }
        Err(e) => {
            eprintln!("Pipeline failed: {}", e);
            std::process::exit(1);
        }
    }
}

fn save_legacy_snapshot_to(
    db_path: &std::path::Path,
    cache_dir: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
    let conn = Connection::open(db_path)?;

    let mut stmt = conn.prepare(
        "SELECT kode, nama, kecamatan, kota, provinsi, lat, lon FROM locations ORDER BY kode",
    )?;

    let mut snapshot = Vec::new();
    let mut rows = stmt.query([])?;
    while let Some(row) = rows.next()? {
        let village: Value = json!({
            "code": row.get::<_, String>(0)?,
            "name": row.get::<_, String>(1)?,
            "district": row.get::<_, String>(2)?,
            "city": row.get::<_, String>(3)?,
            "province": row.get::<_, String>(4)?,
            "lat": row.get::<_, f64>(5)?,
            "lon": row.get::<_, f64>(6)?,
        });
        snapshot.push(village);
    }

    let snapshot_path = cache_dir.join("legacy_snapshot.json");
    std::fs::create_dir_all(snapshot_path.parent().unwrap())?;
    let file = std::fs::File::create(&snapshot_path)?;
    serde_json::to_writer_pretty(file, &snapshot)?;

    eprintln!("Saved legacy snapshot to {}", snapshot_path.display());
    Ok(())
}