use ipld_core::ipld::Ipld;
use mnem_core::codec::{from_canonical_bytes, hash_to_cid};
use mnem_core::id::{EdgeId, NodeId};
use mnem_core::objects::{Edge, Node};
use mnem_core::store::{Blockstore, MemoryBlockstore};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("# mnem M3 + M4 smoke test: MemoryBlockstore + Node/Edge");
println!("# mnem-core version: {}", mnem_core::VERSION);
println!();
let store = MemoryBlockstore::new();
let alice = Node::new(NodeId::new_v7(), "Person")
.with_prop("name", Ipld::String("Alice".into()))
.with_prop("age", Ipld::Integer(30));
let (alice_bytes, alice_cid) = hash_to_cid(&alice)?;
store.put(alice_cid.clone(), alice_bytes)?;
println!("alice: {alice_cid}");
assert!(store.has(&alice_cid)?);
let alice_fetched = store.get(&alice_cid)?.expect("just stored");
let alice2: Node = from_canonical_bytes(&alice_fetched)?;
assert_eq!(alice, alice2, "alice round-trip mismatch");
println!(" round-trip: ok");
let bob = Node::new(NodeId::new_v7(), "Person")
.with_prop("name", Ipld::String("Bob".into()))
.with_prop("age", Ipld::Integer(25));
let (bob_bytes, bob_cid) = hash_to_cid(&bob)?;
store.put(bob_cid.clone(), bob_bytes)?;
println!("bob: {bob_cid}");
let knows = Edge::new(EdgeId::new_v7(), "knows", alice.id, bob.id)
.with_prop("since", Ipld::Integer(2020));
let (knows_bytes, knows_cid) = hash_to_cid(&knows)?;
store.put(knows_cid.clone(), knows_bytes)?;
println!("knows: {knows_cid}");
let knows_fetched = store.get(&knows_cid)?.expect("just stored");
let knows2: Edge = from_canonical_bytes(&knows_fetched)?;
assert_eq!(knows, knows2);
assert_eq!(knows2.src, alice.id);
assert_eq!(knows2.dst, bob.id);
println!(" edge endpoints resolve: alice -> bob");
let (alice_bytes_again, alice_cid_again) = hash_to_cid(&alice)?;
assert_eq!(
alice_cid, alice_cid_again,
"content-addressing not deterministic"
);
store.put(alice_cid_again, alice_bytes_again)?;
assert_eq!(store.len(), 3, "idempotent put should not grow store");
println!("idempotent put: ok (store size still {})", store.len());
let edge_bytes = store.get(&knows_cid)?.expect("exists");
let decode_as_node: Result<Node, _> = from_canonical_bytes(&edge_bytes);
assert!(decode_as_node.is_err(), "edge should not decode as node");
println!("_kind rejection: ok (decoding Edge bytes as Node correctly errors)");
let missing_cid = alice_cid;
store.delete(&missing_cid)?;
assert!(!store.has(&missing_cid)?);
store.delete(&missing_cid)?; println!("delete: ok (double-delete tolerated)");
println!();
println!("# all M3+M4 smoke tests passed. store = {store:?}");
Ok(())
}