//! End-to-end coverage for the `CumSum` standard cell (#281): the generic
//! running-total accumulator.
//!
//! The in-module tests in `aura-std/src/cumsum.rs` drive `eval` directly —
//! they never go through a `PrimitiveBuilder` schema, a `GraphBuilder`-resolved
//! wiring, or a compiled+bootstrapped `FlatGraph`. That is the real seam a
//! data-authored op-script or a Rust builder actually exercises (C24); this
//! file proves `CumSum` is reachable from the public `aura_engine`/`aura_std`
//! construction surface, wires cleanly by declared port name/kind, and
//! accumulates the right running total once actually driven cycle-by-cycle
//! through a real `Harness::run` — the same bar the Sign/Select pair set in
//! `select_sign_e2e.rs`.

use std::sync::mpsc;

use aura_core::{Firing, Scalar, ScalarKind, Timestamp};
use aura_engine::{GraphBuilder, VecSource};
use aura_std::{CumSum, Recorder};

/// A deterministic tick stream, no timestamps/randomness beyond a fixed
/// literal sequence.
fn ticks(values: &[f64]) -> Vec<(Timestamp, Scalar)> {
    values.iter().enumerate().map(|(i, &v)| (Timestamp(i as i64 + 1), Scalar::f64(v))).collect()
}

/// Property: **`CumSum` correctly registers its `PrimitiveBuilder` schema
/// (one `f64` input, one `f64` output) and dispatches through a
/// compiled+bootstrapped `FlatGraph`, accumulating the running total across
/// real engine cycles** — not merely via a direct `eval` call (the in-module
/// `cumsum.rs` unit tests' seam). A schema/wiring regression (wrong port
/// kind, wrong output arity) would fail at `GraphBuilder::build` or
/// `compile_with_params`, before a single cycle runs; a dispatch or
/// state-carry regression would show up in the recorded running totals below.
#[test]
fn cumsum_dispatches_through_a_compiled_graph_and_accumulates() {
    let (tx, rx) = mpsc::channel();
    let mut g = GraphBuilder::new("root");
    let series = g.source_role("series", ScalarKind::F64);
    let cumsum = g.add(CumSum::builder());
    let rec = g.add(Recorder::builder(vec![ScalarKind::F64], Firing::Any, tx));

    g.feed(series, [cumsum.input("series")]);
    g.connect(cumsum.output("value"), rec.input("col[0]"));

    let mut h = g.build().expect("resolves by name").bootstrap_with_params(vec![]).expect("bootstraps");
    h.run(vec![Box::new(VecSource::new(ticks(&[2.0, -0.5, 3.5, 0.0])))]);
    let trace: Vec<f64> = rx.try_iter().map(|(_, row)| row[0].as_f64()).collect();

    assert_eq!(
        trace,
        vec![2.0, 1.5, 5.0, 5.0],
        "running total accumulated across real engine cycles, dispatched through a compiled FlatGraph"
    );
}
