use serde_json::{json, Value};

use crate::{
    automation::{self, PromptRequirement},
    error::HenError,
};

use super::{artifacts::{request_failure_json, run_record_json}, BodyReportOptions};

pub fn run_outcome_json(
    outcome: &automation::RunOutcome,
    body_options: BodyReportOptions,
) -> Value {
    json!({
        "collection": {
            "path": outcome.collection.path.display().to_string(),
            "name": outcome.collection.name,
            "description": outcome.collection.description,
            "requiredInputs": outcome.collection.required_inputs.iter().map(prompt_requirement_json).collect::<Vec<_>>(),
            "requests": outcome.collection.requests.iter().map(|request| {
                json!({
                    "index": request.index,
                    "description": request.description,
                    "method": request.method,
                    "url": request.url,
                    "protocol": request.protocol,
                    "protocolContext": request.protocol_context,
                    "dependencies": request.dependencies,
                })
            }).collect::<Vec<_>>()
        },
        "plan": outcome.plan,
        "selectedRequests": outcome.selected_requests,
        "primaryTarget": outcome.primary_target,
        "executionFailed": outcome.execution_failed,
        "interrupted": outcome.interrupted.is_some(),
        "interruptSignal": outcome.interrupted.map(|signal| signal.as_str()),
        "records": outcome.records.iter().map(|record| run_record_json(record, body_options)).collect::<Vec<_>>(),
        "failures": outcome.failures.iter().map(|failure| request_failure_json(failure, body_options)).collect::<Vec<_>>(),
    })
}

pub fn verification_result_json(result: &automation::VerificationResult) -> Value {
    json!({
        "path": result.path.as_ref().map(|path| path.display().to_string()),
        "name": result.summary.name,
        "description": result.summary.description,
        "requiredInputs": result.required_inputs.iter().map(prompt_requirement_json).collect::<Vec<_>>(),
        "requests": result.summary.requests.iter().map(|request| {
            json!({
                "index": request.index,
                "description": request.description,
                "method": request.method,
                "url": request.url,
                "protocol": request.protocol,
                "protocolContext": request.protocol_context,
            })
        }).collect::<Vec<_>>(),
    })
}

pub fn hen_error_json(error: &HenError) -> Value {
    json!({
        "error": {
            "kind": error.kind().label(),
            "summary": error.summary(),
            "details": error.details(),
            "exitCode": error.exit_code(),
        }
    })
}

fn prompt_requirement_json(prompt: &PromptRequirement) -> Value {
    json!({
        "name": prompt.name,
        "default": prompt.default,
    })
}