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

use _utils::{boxed_error, cleanup_run, create_client, new_run_id, print_summary, require};
use mubit_sdk::{
    FeedbackOptions, GetContextOptions, HandoffOptions, RegisterAgentOptions, TransportMode,
};
use serde_json::json;
use std::error::Error;
use std::time::Instant;

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

    let mut passed = true;
    let mut detail = "validated helper handoff + feedback flow".to_string();
    let mut metrics = json!({});

    let scenario = async {
        let mut planner = RegisterAgentOptions::new("planner");
        planner.run_id = Some(run_id.clone());
        planner.role = "planner".to_string();
        client.register_agent(planner).await?;

        let mut reviewer = RegisterAgentOptions::new("reviewer");
        reviewer.run_id = Some(run_id.clone());
        reviewer.role = "reviewer".to_string();
        client.register_agent(reviewer).await?;

        let mut handoff = HandoffOptions::new(
            "task-1",
            "planner",
            "reviewer",
            "Review the retry policy patch before rollout.",
        );
        handoff.run_id = Some(run_id.clone());
        handoff.requested_action = "review".to_string();
        handoff.metadata = Some(json!({ "source": "rust-helper-example" }));
        let handoff_response = client.handoff(handoff).await?;
        let handoff_id = handoff_response
            .get("handoff_id")
            .and_then(|value| value.as_str())
            .ok_or_else(|| boxed_error(format!("handoff id missing: {handoff_response}")))?
            .to_string();

        let mut feedback = FeedbackOptions::new(handoff_id.clone(), "approve");
        feedback.run_id = Some(run_id.clone());
        feedback.comments = "Patch looks safe for rollout.".to_string();
        feedback.from_agent_id = Some("reviewer".to_string());
        feedback.metadata = Some(json!({ "source": "rust-helper-example" }));
        let feedback_response = client.feedback(feedback).await?;

        let mut context = GetContextOptions::default();
        context.run_id = Some(run_id.clone());
        context.query = Some("What coordination artifacts were recorded for this review handoff?".to_string());
        context.mode = Some("sections".to_string());
        context.sections = vec!["handoffs".to_string(), "feedback".to_string()];
        let context_response = client.get_context(context).await?;

        require(
            handoff_response
                .get("success")
                .and_then(|value| value.as_bool())
                .unwrap_or(false),
            format!("handoff failed: {handoff_response}"),
        )?;
        require(
            feedback_response
                .get("success")
                .and_then(|value| value.as_bool())
                .unwrap_or(false),
            format!("feedback failed: {feedback_response}"),
        )?;
        let section_count = context_response
            .get("section_summaries")
            .and_then(|value| value.as_array())
            .map(|items| items.len())
            .unwrap_or(0);

        metrics = json!({
            "run_id": run_id,
            "handoff_id": handoff_id,
            "feedback_id": feedback_response.get("feedback_id").cloned().unwrap_or(serde_json::Value::Null),
            "section_count": section_count,
        });

        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))
    }
}
