//! SC-9 (Rust half) — Opt-in, OFF by default: the transport is fully silent
//! while the feature flag is off, then activates the moment it is flipped on.
//!
//! This is the Rust feature-off-silence gate (the Swift half — default-OFF
//! `@AppStorage` toggle, TCC scopes NOT in `PermissionScope.allCases`, FDA copy
//! — is asserted separately by grep/`swift test` per the gates file). Here we
//! prove, in-process against the real orchestrator, that with the config store
//! `enabled = false`:
//!
//!   - ZERO outbound sends (the spy records nothing),
//!   - ZERO resolves (a seeded fire-and-return approval stays Pending; no
//!     `approval.resolved` event fires),
//!   - ZERO chat.db reads (the injected `read_max`/`read_new` closures the
//!     poller would call are NEVER invoked).
//!
//! Crucially the silent half pairs a handle FIRST, so the silence is proven to
//! be the *flag* — not an unrelated no-op like a missing recipient. Then the
//! EDGE (flip-on activation): with the SAME paired handle, set `enabled = true`
//! and assert transport activity now occurs (a send happens), proving the gate
//! is the flag.

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

use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;

#[tokio::test]
async fn feature_off_is_silent_then_on_activates() {
    // Start DISABLED, but PAIR a handle up front. Both the harness `store` and
    // the orchestrator's internal store root at the same temp `~/.car/`, so the
    // orchestrator sees this handle. With a recipient present, any silence that
    // follows is attributable ONLY to the enabled flag — not a missing handle.
    let h = Harness::disabled();
    h.store
        .add_handle(PAIRED)
        .expect("pair a handle while the feature is off");
    assert!(
        !h.store.is_enabled().expect("read enabled flag"),
        "precondition: the feature flag defaults OFF",
    );
    assert_eq!(
        h.store.allowlist().expect("read allowlist"),
        vec![PAIRED.to_string()],
        "precondition: a handle IS paired (so silence is the flag, not a missing recipient)",
    );

    // Seed a fire-and-return approval (the v1-target producer). Exactly one
    // `approval.requested` is raised by the seeding itself; the transport's own
    // activity (if any) is what we are testing.
    let approval_id = h.seed_fire_and_return("send the wire transfer").await;
    assert_eq!(
        h.approval_requested_count().await,
        1,
        "seeding raised exactly one approval.requested",
    );

    // -- OUTBOUND while OFF: observe must send nothing. --
    h.orch.observe_and_notify().await;
    assert_eq!(
        h.spy.count(),
        0,
        "feature OFF ⇒ ZERO outbound sends even with an approval pending and a handle paired",
    );

    // -- INBOUND-POLL while OFF: the poller must perform ZERO chat.db reads. --
    // Count every invocation of the injected read closures; feature-off must
    // never call either one (the chat.db read is gated behind the flag).
    let read_max_calls = Arc::new(AtomicI64::new(0));
    let read_new_calls = Arc::new(AtomicI64::new(0));
    let rmc = read_max_calls.clone();
    let rnc = read_new_calls.clone();
    let n = h
        .orch
        .poll_once(
            move || {
                rmc.fetch_add(1, Ordering::SeqCst);
                Ok(0)
            },
            move |_min| {
                rnc.fetch_add(1, Ordering::SeqCst);
                Ok(vec![])
            },
        )
        .await
        .expect("poll_once is infallible when the feature is off");
    assert_eq!(n, 0, "feature OFF ⇒ poll surfaces nothing");
    assert_eq!(
        read_max_calls.load(Ordering::SeqCst),
        0,
        "feature OFF ⇒ ZERO chat.db reads (read_max never invoked)",
    );
    assert_eq!(
        read_new_calls.load(Ordering::SeqCst),
        0,
        "feature OFF ⇒ ZERO chat.db reads (read_new never invoked)",
    );

    // -- INBOUND-RESOLVE while OFF: a direct inbound "approve" resolves nothing. --
    // Even handed a well-formed reply from the paired (allowlisted) handle, the
    // feature-off wall in `handle_inbound` drops it before any parse/resolve.
    h.orch
        .handle_inbound(&inbound(PAIRED, "approve", 1))
        .await;
    assert_eq!(
        h.orch.parse_call_count(),
        0,
        "feature OFF ⇒ ZERO parses (the inbound wall drops before parse)",
    );
    assert!(
        !h.is_resolved(&approval_id).await,
        "feature OFF ⇒ the seeded approval stays Pending (ZERO resolves)",
    );
    assert_eq!(
        h.approval_resolved_count().await,
        0,
        "feature OFF ⇒ ZERO approval.resolved events fired",
    );

    // ===================================================================
    // EDGE — FLIP-ON ACTIVATION. Same paired handle, same pending approval;
    // flipping the flag ON makes the transport active (a send happens). This
    // proves the gate is the FLAG, not an unrelated no-op.
    // ===================================================================
    h.store
        .set_enabled(true)
        .expect("flip the feature ON");
    assert!(
        h.store.is_enabled().expect("read enabled flag"),
        "the feature is now ON",
    );

    h.orch.observe_and_notify().await;
    let calls = h.spy.calls();
    assert_eq!(
        calls.len(),
        1,
        "feature ON (handle paired) ⇒ transport activates and sends exactly one prompt, got {calls:?}",
    );
    let (handle, body) = &calls[0];
    assert_eq!(handle, PAIRED, "the activation send went to the paired handle");
    assert!(
        body.contains("send the wire transfer"),
        "the activation prompt carries the action summary: {body}",
    );
    let code = extract_code(body).expect("the activation prompt carries a per-approval code");
    assert!(!code.is_empty(), "the per-approval code is non-empty: {body}");
}
