//! Property-based tests for Atom serialization round-trip.
//!
//! **Feature: Syna-db, Property 1: Atom Serialization Round-Trip**
//! **Validates: Requirements 5.4, 10.1**

use proptest::prelude::*;
use synadb::types::Atom;

/// Generator for arbitrary Atom values.
fn arb_atom() -> impl Strategy<Value = Atom> {
    prop_oneof![
        1 => Just(Atom::Null),
        // Float with any f64 including NaN, infinity edge cases
        10 => any::<f64>().prop_map(Atom::Float),
        // Int with any i64
        10 => any::<i64>().prop_map(Atom::Int),
        // Text with arbitrary unicode strings (0-1000 chars)
        10 => ".{0,1000}".prop_map(|s: String| Atom::Text(s)),
        // Bytes with arbitrary byte vectors (0-10000 bytes)
        10 => prop::collection::vec(any::<u8>(), 0..10000).prop_map(Atom::Bytes),
    ]
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(100))]

    /// **Feature: Syna-db, Property 1: Atom Serialization Round-Trip**
    ///
    /// For any valid Atom value, serializing with bincode and then deserializing
    /// SHALL produce a value equal to the original.
    #[test]
    fn prop_atom_serialization_roundtrip(atom in arb_atom()) {
        // Serialize the atom
        let serialized = bincode::serialize(&atom).expect("serialization should succeed");

        // Deserialize back
        let deserialized: Atom = bincode::deserialize(&serialized).expect("deserialization should succeed");

        // Special handling for NaN floats - NaN != NaN by IEEE 754
        match (&atom, &deserialized) {
            (Atom::Float(a), Atom::Float(b)) if a.is_nan() && b.is_nan() => {
                // Both are NaN, consider them equal for this test
            }
            _ => {
                prop_assert_eq!(atom, deserialized, "round-trip should preserve value");
            }
        }
    }
}
