#[path = "../support/utils.rs"]
mod _utils;

use _utils::{boxed_error, create_client, print_summary, require};
use serde_json::{json, Value};
use std::error::Error;
use std::time::{Instant, SystemTime, UNIX_EPOCH};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn Error>> {
    let name = "internal_auth_lifecycle";
    let started = Instant::now();
    let client = create_client().await?;
    let username = format!("sdk_example_{}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_millis());
    let mut passed = true;
    let mut detail = "validated raw auth lifecycle".to_string();
    let mut metrics = json!({});

    let scenario = async {
        let health = client.auth.health().await?;
        let created = client.auth.create_user(json!({"username": username, "role": "user"})).await?;
        let listed = client.auth.list_users(json!({})).await?;
        let rotated = client.auth.rotate_user_api_key(json!({"username": username})).await?;
        let fetched = client.auth.get_user(json!({"username": username})).await?;
        let revoked = client.auth.revoke_user_api_key(json!({"username": username})).await?;
        let deleted = client.auth.delete_user(json!({"username": username})).await?;
        let listed_users = listed
            .as_array()
            .cloned()
            .or_else(|| listed.get("users").and_then(Value::as_array).cloned())
            .unwrap_or_default();
        let fetched_user = fetched.get("user").unwrap_or(&fetched);

        require(!health.is_null(), format!("auth health failed: {health}"))?;
        require(created.get("success").and_then(Value::as_bool).unwrap_or(true) || created.get("api_key").is_some(), format!("create_user failed: {created}"))?;
        require(listed_users.iter().any(|item| item.get("username").and_then(Value::as_str) == Some(username.as_str())), format!("list_users missing created user: {listed}"))?;
        require(rotated.get("success").and_then(Value::as_bool).unwrap_or(true) || rotated.get("api_key").is_some(), format!("rotate_user_api_key failed: {rotated}"))?;
        require(fetched_user.get("username").and_then(Value::as_str) == Some(username.as_str()), format!("get_user failed: {fetched}"))?;
        require(revoked.get("success").and_then(Value::as_bool).unwrap_or(true), format!("revoke_user_api_key failed: {revoked}"))?;
        require(deleted.get("success").and_then(Value::as_bool).unwrap_or(true), format!("delete_user failed: {deleted}"))?;

        metrics = json!({"username": username});
        Ok::<(), Box<dyn Error>>(())
    }.await;

    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), true);
    if passed { Ok(()) } else { Err(boxed_error(detail)) }
}
