//! Trust anchor for the tier-2 witness seam (bl-016).
//!
//! Exercises the whole cycle that bl-013/bl-022/bl-014 wired together, end
//! to end, in one test: dispatch ops through the pipeline → each signed
//! witness is appended to the redb oplog → the producer's handle is
//! dropped (fresh-process boundary) → an independent verifier reopens the
//! log from disk and, trusting nothing but the actor's public key:
//!
//!   1. verifies every persisted operation's signature (the oplog body);
//!   2. reconstructs each `PipelineWitness` from its payload and verifies its
//!      own Ed25519 signature;
//!   3. replays the witness chain — applying each witness's embedded
//!      state-changing op to a fresh commit layer — and confirms the
//!      reconstructed `state_root` reproduces the one the witness attests, at
//!      every step.
//!
//! This is the executable proof of the `vp-004` provenance claim.

use std::sync::Arc;

use ed25519_dalek::SigningKey;
use ontoref_commit::BinaryMerkle;
use ontoref_oplog::OpLog;
use ontoref_ops::{dispatch_op, OpContext, PipelineWitness};
use ontoref_types::operation::{OpPayload, Operation};
use ontoref_types::{canonical, PublicKey};

const SEED: [u8; 32] = [42u8; 32];

#[test]
fn full_cycle_dispatch_persist_replay_verify() {
    let dir = tempfile::tempdir().expect("tempdir");
    let oplog_path = dir.path().join("oplog.redb");

    // The actor identity an independent verifier will check against —
    // never the producer-declared key on the op itself.
    let expected_actor = PublicKey::from_signing_key(&SigningKey::from_bytes(&SEED));

    // ── Producer side: two dispatches share one oplog. Scoped so the redb
    //    handle and the in-memory commit layer are dropped before the
    //    verifier reopens the file — a genuine fresh-process boundary.
    let attested_roots: Vec<[u8; 32]> = {
        let oplog = Arc::new(OpLog::open(&oplog_path).expect("open oplog"));
        let mut ctx = OpContext::new_in_memory("developer", "", SigningKey::from_bytes(&SEED))
            .with_oplog(Arc::clone(&oplog));

        let mut roots = Vec::new();
        for topic in ["structure-that-remembers", "witness-as-axis-seam"] {
            let inputs = serde_json::json!({
                "topic": topic,
                "engaged_tensions": ["witness-as-axis-seam"],
                "synthesis_state": "held",
                "motion_direction": "TowardSynthesis",
            });
            let result = dispatch_op("evaluate_ondaod", &inputs, &mut ctx).expect("dispatch");
            assert!(
                result.oplog_op_id.is_some(),
                "every dispatch must persist its witness"
            );
            roots.push(result.witness.state_root);
        }
        roots
    };

    // ── Verifier side: a fresh handle onto the durable log. Trusts only
    //    the actor public key; reconstructs everything else.
    let reopened = OpLog::open(&oplog_path).expect("reopen oplog in a fresh handle");
    assert_eq!(
        reopened.len().expect("len"),
        2,
        "both witnesses are durable across the handle boundary"
    );

    let ops = reopened.all_ops_in_hlc_order().expect("replay order");
    assert_eq!(ops.len(), 2);

    // Replay the witness chain, rebuilding the attested state_root from the
    // witnesses' own embedded ops.
    let mut replay_layer = BinaryMerkle::new();
    for (idx, op) in ops.iter().enumerate() {
        // (1) The oplog body signature verifies, and against the EXPECTED
        //     actor — not merely self-consistently.
        op.verify_signature()
            .expect("persisted operation signature must verify");
        assert_eq!(
            op.body.actor, expected_actor,
            "the persisted witness must be signed by the known actor"
        );

        // Causal chain: the second witness extends the first.
        if idx == 0 {
            assert!(op.body.parents.is_empty(), "first witness has no parents");
        } else {
            assert_eq!(
                op.body.parents,
                vec![ops[idx - 1].id()],
                "each witness chains onto the previous oplog head"
            );
        }

        assert!(
            matches!(op.body.payload, OpPayload::Witness { .. }),
            "every entry in this log is a pipeline witness"
        );
        if let OpPayload::Witness {
            effects_hash,
            extra_payload,
            op_id,
            state_root,
            witness_shape,
            witness_sig,
        } = op.body.payload.clone()
        {
            // (2) Reconstruct the PipelineWitness and verify its own signature.
            let reconstructed = PipelineWitness {
                op_id: op_id.clone(),
                state_root,
                effects_hash,
                extra_payload: extra_payload.clone(),
                witness_shape,
                actor: op.body.actor,
                signature: witness_sig,
            };
            reconstructed
                .verify()
                .expect("reconstructed pipeline witness must verify");
            assert_eq!(op_id, "evaluate_ondaod");

            // (3) Replay: the witness's embedded op is the state-changing
            //     EntityAssert the pipeline applied. Applying it to the
            //     running layer must reproduce the attested state_root — and
            //     it must equal what the producer returned at dispatch time.
            let embedded: Operation =
                canonical::decode(&extra_payload).expect("embedded op decodes");
            embedded
                .verify_signature()
                .expect("embedded state-changing op also verifies");
            replay_layer.apply(&embedded);
            assert_eq!(
                replay_layer.root(),
                state_root,
                "replaying the witness chain reproduces the attested state_root at step {idx}"
            );
            assert_eq!(
                state_root, attested_roots[idx],
                "persisted root matches the one returned at dispatch time"
            );
        }
    }
}
