//! Fieldtest c0006 #5 — a mis-wired recording edge is rejected at bootstrap.
//!
//! Supports the "record interior streams" axis from the failure side: a recording
//! node declares typed input slots like any consumer, so an edge whose producer
//! field kind mismatches the slot kind is rejected at bootstrap (the existing
//! per-field 0005 check; recording adds no new hole). Correct behaviour here is
//! REJECTION — this fixture asserts the rejection happens with the documented
//! error, before any data flows. Mirrors the 0006 spec's must-fail fixture.

use std::sync::mpsc;

use aura_core::{Ctx, FieldSpec, Firing, InputSpec, Node, NodeSchema, Scalar, ScalarKind, Timestamp};
use aura_engine::{BootstrapError, Edge, Harness, SourceSpec, Target};

/// A producer that emits one i64 field.
struct I64Source {
    out: [Scalar; 1],
}
impl Node for I64Source {
    fn schema(&self) -> NodeSchema {
        NodeSchema {
            inputs: vec![InputSpec {
                kind: ScalarKind::I64,
                lookback: 1,
                firing: Firing::Any,
            }],
            output: vec![FieldSpec { name: "v", kind: ScalarKind::I64 }],
        }
    }
    fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Scalar]> {
        let w = ctx.i64_in(0);
        if w.is_empty() {
            return None;
        }
        self.out[0] = Scalar::I64(w[0]);
        Some(&self.out)
    }
}

/// A recorder declaring an f64 input slot.
struct Recorder {
    tx: mpsc::Sender<(Timestamp, f64)>,
}
impl Node for Recorder {
    fn schema(&self) -> NodeSchema {
        NodeSchema {
            inputs: vec![InputSpec {
                kind: ScalarKind::F64,
                lookback: 1,
                firing: Firing::Any,
            }],
            output: vec![],
        }
    }
    fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Scalar]> {
        let w = ctx.f64_in(0);
        if w.is_empty() {
            return None;
        }
        let _ = self.tx.send((ctx.now(), w[0]));
        None
    }
}

fn main() {
    let (tx, _rx) = mpsc::channel();

    // Bind the i64 producer field into the f64 recorder slot -> must be rejected.
    let err = Harness::bootstrap(
        vec![
            Box::new(I64Source { out: [Scalar::I64(0)] }),
            Box::new(Recorder { tx }),
        ],
        vec![SourceSpec {
            kind: ScalarKind::I64,
            targets: vec![Target { node: 0, slot: 0 }],
        }],
        vec![Edge { from: 0, to: 1, slot: 0, from_field: 0 }],
    )
    .unwrap_err();

    println!("err = {err:?}");
    assert_eq!(
        err,
        BootstrapError::KindMismatch {
            producer: ScalarKind::I64,
            consumer: ScalarKind::F64,
        },
        "kind-mismatched recorder edge must be rejected at bootstrap"
    );
    println!("c0006_5 OK: mis-wired recording edge rejected with KindMismatch");
}
