//! Core logic and types for Episteme (StemeDB).
//!
//! This crate defines the fundamental data structures like `Assertion`,
//! `SignatureEntry`, and the core traits for the knowledge graph.

/// System-wide limits and defaults.
pub mod limits;
/// Zero-copy serialization utilities.
pub mod serde;
/// Cryptographic signing utilities for assertions.
pub mod signing;
/// Shared test helpers (builders, factories) for the workspace.
pub mod testing;
/// Core data types for StemeDB assertions and signatures.
pub mod types;

/// A simple hello world function for testing the core crate.
pub fn hello_world() -> String {
    "Hello from Episteme Core!".to_string()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::{
        Assertion, Epoch, HlcTimestamp, LifecycleStage, ObjectValue, SignatureEntry, SourceClass,
        Supersession, SupersessionType, Vote,
    };
    use rkyv::check_archived_root;
    use rkyv::ser::serializers::AllocSerializer;
    use rkyv::ser::Serializer;
    use rkyv::Deserialize;

    #[test]
    fn test_hello_world() {
        assert_eq!(hello_world(), "Hello from Episteme Core!");
    }

    #[test]
    fn test_assertion_serialization_roundtrip() {
        let assertion = Assertion {
            subject: "Tesla_Inc".to_string(),
            predicate: "has_revenue".to_string(),
            object: ObjectValue::Number(96.7),
            parent_hash: None,
            source_hash: [0u8; 32],
            source_class: SourceClass::Clinical,
            visual_hash: Some([1u8; 8]),
            epoch: Some([2u8; 32]),
            source_metadata: None,
            lifecycle: LifecycleStage::Approved,
            signatures: vec![SignatureEntry {
                agent_id: [2u8; 32],
                signature: [3u8; 64],
                timestamp: 123456789,
                version: 1,
            }],
            confidence: 0.95,
            timestamp: 123456789,
            hlc_timestamp: HlcTimestamp::default(),
            vector: Some(vec![0.1, 0.2, 0.3]),
        };

        // Serialize
        let mut serializer = AllocSerializer::<4096>::default();
        serializer.serialize_value(&assertion).expect("Failed to serialize");
        let bytes = serializer.into_serializer().into_inner();

        // Validate
        let archived = check_archived_root::<Assertion>(&bytes)
            .expect("Failed to validate archived assertion");

        // Deserialize
        let deserialized: Assertion =
            archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

        assert_eq!(assertion, deserialized);
        assert_eq!(deserialized.subject, "Tesla_Inc");
        assert_eq!(deserialized.visual_hash, Some([1u8; 8]));
        assert_eq!(deserialized.epoch, Some([2u8; 32]));
        assert_eq!(deserialized.lifecycle, LifecycleStage::Approved);
    }

    #[test]
    fn test_lifecycle_stage_serialization_roundtrip() {
        // Test all lifecycle stages survive serialization
        let stages = [
            LifecycleStage::Proposed,
            LifecycleStage::UnderReview,
            LifecycleStage::Approved,
            LifecycleStage::Deprecated,
            LifecycleStage::Rejected,
        ];

        for stage in stages {
            let assertion = Assertion {
                subject: "test".to_string(),
                predicate: "lifecycle_test".to_string(),
                object: ObjectValue::Text(format!("{:?}", stage)),
                parent_hash: None,
                source_hash: [0u8; 32],
                source_class: SourceClass::Expert,
                visual_hash: None,
                epoch: None,
                source_metadata: None,
                lifecycle: stage,
                signatures: vec![],
                confidence: 1.0,
                timestamp: 0,
                hlc_timestamp: HlcTimestamp::default(),
                vector: None,
            };

            let mut serializer = AllocSerializer::<4096>::default();
            serializer.serialize_value(&assertion).expect("Failed to serialize");
            let bytes = serializer.into_serializer().into_inner();

            let archived = check_archived_root::<Assertion>(&bytes)
                .expect("Failed to validate archived assertion");
            let deserialized: Assertion =
                archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

            assert_eq!(
                deserialized.lifecycle, stage,
                "Lifecycle stage {:?} should survive round-trip",
                stage
            );
        }
    }

    #[test]
    fn test_lifecycle_stage_default() {
        // Verify that Default gives us Proposed (the safe default)
        assert_eq!(LifecycleStage::default(), LifecycleStage::Proposed);
    }

    #[test]
    fn test_epoch_serialization_roundtrip() {
        let epoch = Epoch {
            id: [1u8; 32],
            name: "Newtonian Physics".to_string(),
            supersedes: Some([0u8; 32]),
            supersession_type: Some(SupersessionType::Refinement),
            start_timestamp: 1000,
            end_timestamp: None,
        };

        // Serialize
        let mut serializer = AllocSerializer::<4096>::default();
        serializer.serialize_value(&epoch).expect("Failed to serialize");
        let bytes = serializer.into_serializer().into_inner();

        // Validate
        let archived =
            check_archived_root::<Epoch>(&bytes).expect("Failed to validate archived epoch");

        // Deserialize
        let deserialized: Epoch =
            archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

        assert_eq!(epoch, deserialized);
        assert_eq!(deserialized.name, "Newtonian Physics");
        assert_eq!(deserialized.supersession_type, Some(SupersessionType::Refinement));
    }

    #[test]
    fn test_supersession_serialization_roundtrip() {
        let supersession = Supersession {
            target_hash: [1u8; 32],
            supersession_type: SupersessionType::Invalidate,
            reason: "Proposal treated as approved. See incident INC-2024-001".to_string(),
            new_hash: Some([2u8; 32]),
            timestamp: 1704067200,
            hlc_timestamp: None, // Legacy: no HLC for backward compat test
            agent_id: [3u8; 32],
            signature: [4u8; 64],
        };

        // Serialize
        let mut serializer = AllocSerializer::<4096>::default();
        serializer.serialize_value(&supersession).expect("Failed to serialize");
        let bytes = serializer.into_serializer().into_inner();

        // Validate
        let archived = check_archived_root::<Supersession>(&bytes)
            .expect("Failed to validate archived supersession");

        // Deserialize
        let deserialized: Supersession =
            archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

        assert_eq!(supersession, deserialized);
        assert_eq!(deserialized.target_hash, [1u8; 32]);
        assert_eq!(deserialized.supersession_type, SupersessionType::Invalidate);
        assert_eq!(deserialized.reason, "Proposal treated as approved. See incident INC-2024-001");
        assert_eq!(deserialized.new_hash, Some([2u8; 32]));
    }

    #[test]
    fn test_supersession_type_all_variants() {
        // Test all supersession types survive serialization
        let types = [
            SupersessionType::Invalidate,
            SupersessionType::Temporal,
            SupersessionType::Refinement,
            SupersessionType::RequiresReview,
            SupersessionType::Additive,
        ];

        for stype in types {
            let supersession = Supersession {
                target_hash: [0u8; 32],
                supersession_type: stype,
                reason: format!("{:?} test", stype),
                new_hash: None,
                timestamp: 0,
                hlc_timestamp: None,
                agent_id: [0u8; 32],
                signature: [0u8; 64],
            };

            let mut serializer = AllocSerializer::<4096>::default();
            serializer.serialize_value(&supersession).expect("Failed to serialize");
            let bytes = serializer.into_serializer().into_inner();

            let archived = check_archived_root::<Supersession>(&bytes)
                .expect("Failed to validate archived supersession");
            let deserialized: Supersession =
                archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

            assert_eq!(
                deserialized.supersession_type, stype,
                "SupersessionType {:?} should survive round-trip",
                stype
            );
        }
    }

    #[test]
    fn test_vote_serialization_roundtrip() {
        let vote = Vote {
            assertion_hash: [1u8; 32],
            agent_id: [2u8; 32],
            weight: 0.8,
            signature: [3u8; 64],
            timestamp: 123456789,
            source_url: None,
            observed_context: None,
        };

        // Serialize
        let mut serializer = AllocSerializer::<4096>::default();
        serializer.serialize_value(&vote).expect("Failed to serialize");
        let bytes = serializer.into_serializer().into_inner();

        // Validate
        let archived =
            check_archived_root::<Vote>(&bytes).expect("Failed to validate archived vote");

        // Deserialize
        let deserialized: Vote =
            archived.deserialize(&mut rkyv::Infallible).expect("Failed to deserialize");

        assert_eq!(vote, deserialized);
        assert_eq!(deserialized.assertion_hash, [1u8; 32]);
        assert_eq!(deserialized.weight, 0.8);
    }
}
