use std::fs;
use std::path::Path;

use openapiv3::OpenAPI;

const SPEC_PATH: &str = "openapi/openapi.yaml";

fn main() {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    let spec_path = Path::new(&manifest_dir).join(SPEC_PATH);

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

    let raw = fs::read_to_string(&spec_path).unwrap_or_else(|e| {
        panic!("Failed to read {}: {}", spec_path.display(), e);
    });

    let val: serde_json::Value = serde_yaml::from_str(&raw).unwrap_or_else(|e| {
        panic!("Failed to parse {}: {}", spec_path.display(), e);
    });

    let spec: OpenAPI = serde_json::from_value(val).unwrap_or_else(|e| {
        panic!("Failed to deserialize OpenAPI spec: {e}");
    });

    let mut generator = progenitor::Generator::default();
    let tokens = generator.generate_tokens(&spec).unwrap_or_else(|e| {
        panic!("Failed to generate SDK code: {e}");
    });
    let ast = syn::parse2(tokens).unwrap_or_else(|e| {
        panic!("Failed to parse generated code: {e}");
    });

    let out_path = Path::new(&out_dir).join("api.rs");
    fs::write(&out_path, prettyplease::unparse(&ast)).unwrap_or_else(|e| {
        panic!("Failed to write {}: {}", out_path.display(), e);
    });
}
