//! SC-5 — Ambiguity fails safe.
//!
//! With 2+ approvals pending for one sender and a bare `approve` (no code),
//! NOTHING is resolved and the daemon sends exactly one disambiguation reply
//! listing the pending codes. No "most-recent" guessing.
//!
//! Edge: an unknown / already-resolved code resolves nothing.

mod messaging_harness;
use messaging_harness::{extract_code, inbound, Harness, PAIRED};

#[tokio::test]
async fn two_pending_bare_approve_resolves_nothing_and_disambiguates() {
    let h = Harness::enabled_paired();
    let id_a = h.seed_fire_and_return("send email A").await;
    let id_b = h.seed_fire_and_return("run applescript B").await;

    // Both get prompted (two outbound sends, each with its own code).
    h.orch.observe_and_notify().await;
    let prompts = h.spy.calls();
    assert_eq!(prompts.len(), 2, "two prompts for two pending approvals");
    let code_a = extract_code(&prompts[0].1).unwrap();
    let code_b = extract_code(&prompts[1].1).unwrap();
    assert_ne!(code_a, code_b, "each approval gets a distinct code");

    // Bare `approve` — ambiguous with 2 pending.
    h.orch.handle_inbound(&inbound(PAIRED, "approve", 1)).await;

    // NOTHING resolved.
    assert!(!h.is_resolved(&id_a).await, "approval A stays Pending");
    assert!(!h.is_resolved(&id_b).await, "approval B stays Pending");
    assert_eq!(
        h.approval_resolved_count().await,
        0,
        "no approval.resolved fired on the ambiguous bare approve"
    );

    // EXACTLY ONE disambiguation reply, to the sender, listing BOTH codes.
    let all = h.spy.calls();
    assert_eq!(all.len(), 3, "two prompts + one disambiguation reply");
    let (handle, reply) = &all[2];
    assert_eq!(handle, PAIRED, "disambiguation reply goes to the sender");
    assert!(
        reply.contains(&code_a) && reply.contains(&code_b),
        "disambiguation reply lists both pending codes: {reply}"
    );
}

#[tokio::test]
async fn unknown_code_resolves_nothing() {
    let h = Harness::enabled_paired();
    let id = h.seed_fire_and_return("send the report").await;
    h.orch.observe_and_notify().await;
    let sends_before = h.spy.count();

    // A bogus code that maps to no approval.
    h.orch
        .handle_inbound(&inbound(PAIRED, "Z99 approve", 1))
        .await;

    assert!(
        !h.is_resolved(&id).await,
        "an unknown code resolves nothing"
    );
    assert_eq!(
        h.spy.count(),
        sends_before,
        "a named (but unknown) code does NOT trigger a disambiguation reply"
    );
}

#[tokio::test]
async fn already_resolved_code_resolves_nothing_second_time() {
    let h = Harness::enabled_paired();
    let id = h.seed_fire_and_return("approve once").await;
    h.orch.observe_and_notify().await;
    let code = extract_code(&h.spy.calls()[0].1).unwrap();

    // First resolve lands.
    h.orch
        .handle_inbound(&inbound(PAIRED, &format!("{code} approve"), 1))
        .await;
    assert!(h.is_resolved(&id).await);
    let resolved_after_first = h.approval_resolved_count().await;

    // Re-sending the now-consumed code resolves nothing further (no crash, no
    // second approval.resolved).
    h.orch
        .handle_inbound(&inbound(PAIRED, &format!("{code} approve"), 2))
        .await;
    assert_eq!(
        h.approval_resolved_count().await,
        resolved_after_first,
        "a consumed code cannot re-resolve"
    );
}
