use std::fs;
use std::path::PathBuf;
use std::process::Command;

use serde_json::Value;

#[test]
#[ignore = "requires nightly rustdoc JSON output"]
fn embed_docs_show_original_fields() {
    let status = Command::new("cargo")
        .args([
            "+nightly",
            "rustdoc",
            "--manifest-path",
            "tests/doc-fixture/Cargo.toml",
            "--lib",
            "-Z",
            "unstable-options",
            "--output-format",
            "json",
        ])
        .status()
        .expect("failed to invoke cargo +nightly rustdoc");

    assert!(status.success(), "cargo +nightly rustdoc failed");

    let json_path = PathBuf::from("tests/doc-fixture/target/doc/read_only_doc_fixture.json");
    let json = fs::read_to_string(&json_path).expect("failed to read rustdoc JSON output");
    let root: Value = serde_json::from_str(&json).expect("failed to parse rustdoc JSON output");

    let index = root["index"]
        .as_object()
        .expect("rustdoc JSON index should be an object");

    let device = index
        .values()
        .find(|item| item["name"].as_str() == Some("Device"))
        .expect("Device item not found in rustdoc JSON");

    let fields = device["inner"]["struct"]["kind"]["plain"]["fields"]
        .as_array()
        .expect("Device fields should be an array")
        .to_owned();

    let field_names: Vec<&str> = fields
        .iter()
        .map(|field_id| {
            let field_id = field_id
                .as_u64()
                .expect("field id should be an integer")
                .to_string();
            index[&field_id]["name"]
                .as_str()
                .expect("field item should have a name")
        })
        .collect();

    assert_eq!(field_names, ["handle", "label", "mutable"]);

    let handle_id = fields
        .first()
        .and_then(Value::as_u64)
        .expect("handle field id should exist")
        .to_string();
    assert_eq!(
        index[&handle_id]["docs"].as_str(),
        Some("Stable device handle.")
    );
}
