use std::sync::Arc;

use axum::extract::{Query, State};
use axum::http::StatusCode;
use axum::Json;

use crate::commands::portal::dto::PortalRunDiff;
use crate::commands::portal::errors::{internal_error, not_found_error};
use crate::commands::portal::query::{CompareQuery, ErrorResponse};
use crate::commands::portal::run_analysis::resolve_run_path;
use crate::commands::portal::state::PortalState;

pub(crate) async fn compare_runs_handler(
    State(state): State<Arc<PortalState>>,
    Query(query): Query<CompareQuery>,
) -> Result<Json<PortalRunDiff>, (StatusCode, Json<ErrorResponse>)> {
    let left_path = resolve_run_path(&state.run_dir, &query.left)?;
    let right_path = resolve_run_path(&state.run_dir, &query.right)?;
    let left = harn_vm::orchestration::load_run_record(&left_path).map_err(|error| {
        if left_path.exists() {
            internal_error(format!("failed to load left run: {error}"))
        } else {
            not_found_error(format!("left run not found: {}", query.left))
        }
    })?;
    let right = harn_vm::orchestration::load_run_record(&right_path).map_err(|error| {
        if right_path.exists() {
            internal_error(format!("failed to load right run: {error}"))
        } else {
            not_found_error(format!("right run not found: {}", query.right))
        }
    })?;
    let diff = harn_vm::orchestration::diff_run_records(&left, &right);
    Ok(Json(PortalRunDiff {
        left_path: query.left,
        right_path: query.right,
        identical: diff.identical,
        status_changed: diff.status_changed,
        left_status: diff.left_status,
        right_status: diff.right_status,
        stage_diffs: diff.stage_diffs,
        tool_diffs: diff.tool_diffs,
        observability_diffs: diff.observability_diffs,
        transition_count_delta: diff.transition_count_delta,
        artifact_count_delta: diff.artifact_count_delta,
        checkpoint_count_delta: diff.checkpoint_count_delta,
    }))
}
