//! Admin-only case reset endpoint: POST /web/cases/{case_id}/reset.
//!
//! Verifies the sticky-Manual rule for the reset path: a clinician-set
//! `OnelinerState::Manual` must survive an admin-triggered reset, while
//! all LLM-derived oneliner states (`Ready`, `Empty`, `Error`) are
//! wiped as before. The wider „transcripts removed, .m4a.failed
//! re-armed" contract is covered in `analyze_test.rs`.

mod common;

use axum::http::{StatusCode, header};
use doctate_common::oneliners::OnelinerState;
use tower::util::ServiceExt;

use common::{
    ONELINER_FILENAME, TestConfig, csrf_form_post, login_with_csrf, paths, seed_case,
    seed_oneliner_ready, seed_oneliner_state, seed_recording, test_admin,
};

fn cfg_admin(label: &'static str) -> std::sync::Arc<doctate_server::config::Config> {
    TestConfig::new()
        .with_label(label)
        .with_user(test_admin("dr_a"))
        .build()
}

#[tokio::test]
async fn reset_case_preserves_manual_oneliner_override() {
    // Bug regression: an admin reset must NOT destroy a clinician's
    // manual oneliner override. The Manual variant is sticky for the
    // lifetime of the case.
    let cfg = cfg_admin("reset-manual");
    let case_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
    let dir = seed_case(&cfg.data_path, "dr_a", case_id);
    seed_recording(&dir, "2026-04-26T10-00-00Z", Some("Knie links"));

    let manual_text = "55 J., Knieschmerz links — manuell vom Arzt";
    seed_oneliner_state(
        &dir,
        &OnelinerState::Manual {
            text: manual_text.into(),
            set_at: "2026-04-26T12:00:00Z".into(),
        },
    );

    let (app, store) = doctate_server::create_router_and_session_store(cfg);
    let (cookie, csrf) = login_with_csrf(&app, &store, "dr_a", "s").await;

    let resp = app
        .oneshot(csrf_form_post(
            paths::case_reset(case_id),
            &cookie,
            &csrf,
            "",
        ))
        .await
        .unwrap();
    assert_eq!(resp.status(), StatusCode::SEE_OTHER);
    assert_eq!(
        resp.headers().get(header::LOCATION).unwrap(),
        &format!("/web/cases/{case_id}")
    );

    // Recording metadata sidecar was wiped (the rest of the reset
    // semantics still works).
    assert!(!dir.join("2026-04-26T10-00-00Z.json").exists());
    // …but the Manual override is untouched.
    let bytes = std::fs::read(dir.join(ONELINER_FILENAME))
        .expect("oneliner.json must still exist after reset");
    let on_disk: OnelinerState =
        serde_json::from_slice(&bytes).expect("oneliner.json must still be valid JSON");
    match on_disk {
        OnelinerState::Manual { text, .. } => {
            assert_eq!(text, manual_text, "manual text must be byte-identical");
        }
        other => panic!("expected Manual after reset, got {other:?}"),
    }
}

#[tokio::test]
async fn reset_case_removes_auto_oneliner() {
    // Positive counterpart: a `Ready` oneliner (LLM-derived auto state)
    // must still be wiped by reset — otherwise the wrapper would be
    // protecting too much.
    let cfg = cfg_admin("reset-auto");
    let case_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb";
    let dir = seed_case(&cfg.data_path, "dr_a", case_id);
    seed_recording(&dir, "2026-04-26T10-00-00Z", Some("Knie links"));
    seed_oneliner_ready(&dir, "knee, left, pain");

    let (app, store) = doctate_server::create_router_and_session_store(cfg);
    let (cookie, csrf) = login_with_csrf(&app, &store, "dr_a", "s").await;

    let resp = app
        .oneshot(csrf_form_post(
            paths::case_reset(case_id),
            &cookie,
            &csrf,
            "",
        ))
        .await
        .unwrap();
    assert_eq!(resp.status(), StatusCode::SEE_OTHER);

    assert!(
        !dir.join(ONELINER_FILENAME).exists(),
        "Ready oneliner must be wiped by reset"
    );
}
