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

use _utils::{
    boxed_error, cleanup_run, create_client, is_permission_denied_like, new_run_id, print_summary,
    require, ScenarioConfig,
};
use mubit_sdk::TransportMode;
use serde_json::{json, Value};
use std::error::Error;
use std::time::Instant;

fn extract_result_count(payload: &Value) -> usize {
    if let Some(items) = payload.as_array() {
        return items.iter().filter(|item| item.is_object()).count();
    }
    payload
        .get("results")
        .and_then(Value::as_array)
        .map(|items| items.iter().filter(|item| item.is_object()).count())
        .unwrap_or(0)
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn Error>> {
    let name = "core_direct_search_optional";
    let started = Instant::now();
    let config = ScenarioConfig::from_env();
    let client = create_client().await?;
    let run_id = new_run_id("core_direct_search_optional");
    client.set_run_id(Some(run_id.clone()));
    client.set_transport(TransportMode::Http);

    let mut passed = true;
    let mut detail = "validated optional core direct-search".to_string();
    let mut metrics = json!({});

    let scenario = async {
        match client
            .core
            .search(json!({
                "query": "direct core semantic search probe",
                "k": 5,
            }))
            .await
        {
            Ok(payload) => {
                require(
                    payload.is_array() || payload.is_object(),
                    format!("core.search payload must be dict/list: {payload}"),
                )?;

                metrics = json!({
                    "run_id": run_id,
                    "enabled": true,
                    "result_count": extract_result_count(&payload),
                });
                detail = "validated optional core direct-search (enabled)".to_string();
            }
            Err(err) => {
                if config.expect_direct_search_enabled {
                    return Err(boxed_error(format!(
                        "core.search expected enabled but failed: {err}"
                    )));
                }
                let message = err.to_string();
                require(
                    is_permission_denied_like(&message),
                    format!(
                        "core.search should fail with permission denied when disabled: {message}"
                    ),
                )?;

                metrics = json!({
                    "run_id": run_id,
                    "enabled": false,
                    "message": message,
                });
                detail = "validated optional core direct-search (disabled)".to_string();
            }
        }

        Ok::<(), Box<dyn Error>>(())
    }
    .await;

    if let Err(err) = scenario {
        passed = false;
        detail = err.to_string();
    }

    let cleanup_ok = cleanup_run(&client, &run_id).await;
    if !cleanup_ok {
        passed = false;
        detail = format!("{detail} | cleanup failures");
    }

    print_summary(
        name,
        passed,
        &detail,
        &metrics,
        started.elapsed().as_secs_f64(),
        cleanup_ok,
    );

    if passed {
        Ok(())
    } else {
        Err(boxed_error(detail))
    }
}
