//! Drive the mizan-rust kernel against a live FastAPI fixture app and
//! print every response. Used by `run_wire_parity.sh` which:
//!
//! 1. Boots `tests/afi/fastapi_app.py` via uvicorn on port 8765.
//! 2. Polls `/openapi.json` until the server is up.
//! 3. Runs `cargo run --bin drive_kernel -- http://127.0.0.1:8765/api/mizan`.
//! 4. Diffs the stdout against a committed snapshot.
//!
//! The kernel exercises every endpoint the fixture declares: the two
//! plain functions (`echo`, `whoami`), the two-function `user` context,
//! the `update_profile` mutation, the `find_user` Optional path, and
//! the `rename_user` merge mutation.

use std::env;
use std::process::ExitCode;

use mizan_rust::{MizanClient, MizanConfig};
use serde_json::{json, Value};


#[tokio::main]
async fn main() -> ExitCode {
    let base_url = env::args().nth(1)
        .unwrap_or_else(|| "http://127.0.0.1:8765/api/mizan".to_string());
    let client = MizanClient::new(MizanConfig {
        base_url,
        session: false,
        ..Default::default()
    });

    let mut failures = 0usize;
    failures += probe(&client, "echo", json!({"text": "hello"})).await;
    failures += probe(&client, "whoami", json!({})).await;
    failures += probe(&client, "find_user", json!({"user_id": 99999})).await;
    failures += probe(&client, "update_profile", json!({"user_id": 5, "name": "Ryth"})).await;
    failures += probe(&client, "rename_user", json!({"user_id": 5, "name": "RythR"})).await;

    failures += probe_context(&client, "user", json!({"user_id": 5})).await;

    if failures > 0 {
        eprintln!("[drive_kernel] {failures} probe(s) failed");
        ExitCode::FAILURE
    } else {
        ExitCode::SUCCESS
    }
}


async fn probe(client: &MizanClient, fn_name: &str, args: Value) -> usize {
    match client.call(fn_name, args.clone()).await {
        Ok(result) => {
            println!("call {fn_name} args={args} -> {result}");
            0
        }
        Err(err) => {
            eprintln!("call {fn_name} args={args} -> ERR {err}");
            1
        }
    }
}


async fn probe_context(client: &MizanClient, name: &str, params: Value) -> usize {
    match client.fetch_context(name, &params).await {
        Ok(data) => {
            println!("ctx {name} params={params} -> {data}");
            0
        }
        Err(err) => {
            eprintln!("ctx {name} params={params} -> ERR {err}");
            1
        }
    }
}
