//! Assertion data structures - the atomic unit of knowledge.

use rkyv::{Archive, Deserialize, Serialize};

use super::{EntityId, EpochId, Hash, HlcTimestamp, PHash, RelationId};
use crate::types::{LifecycleStage, SourceClass};

/// The atomic unit of knowledge in StemeDB.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct Assertion {
    // 1. The Fact (The "What")
    /// The subject of the assertion (e.g., "Tesla_Inc").
    pub subject: EntityId,
    /// The predicate or relation (e.g., "has_revenue").
    pub predicate: RelationId,
    /// The object or value (e.g., 96.7 billion).
    pub object: ObjectValue,

    // 2. The Lineage (The "Why")
    /// The hash of the parent assertion, if this is a modification (fork).
    pub parent_hash: Option<Hash>,
    /// The hash of the source evidence (PDF, URL, Log).
    pub source_hash: Hash,
    /// The authority tier of the source (Regulatory, Clinical, Anecdotal, etc.).
    /// Enables indexing by tier and tier-based decay rates.
    pub source_class: SourceClass,
    /// The perceptual hash for visual anchoring (if applicable).
    pub visual_hash: Option<PHash>,
    /// The epoch this assertion belongs to (if any).
    pub epoch: Option<EpochId>,
    /// Structured source metadata as a JSON-encoded byte string.
    /// Schema is domain-specific (journal info, social metrics, etc.).
    /// Use `Vec<u8>` for rkyv zero-copy compatibility.
    pub source_metadata: Option<Vec<u8>>,
    /// The lifecycle stage (Proposed, UnderReview, Approved, Deprecated, Rejected).
    pub lifecycle: LifecycleStage,

    // 3. Meta-Cognition (The "Who" and "How sure")
    /// List of agent signatures vouching for this assertion.
    pub signatures: Vec<SignatureEntry>,
    /// The confidence score (0.0 to 1.0).
    pub confidence: f32,
    /// The timestamp when the assertion was created (Unix epoch).
    pub timestamp: u64,
    /// Hybrid Logical Clock timestamp for distributed causal ordering.
    ///
    /// Provides total ordering even with clock skew between nodes:
    /// 1. NTP64 time (includes physical + logical counter)
    /// 2. Node ID for deterministic tiebreaker
    ///
    /// Used by `HlcRecencyLens` for consistent "most recent" resolution.
    pub hlc_timestamp: HlcTimestamp,
    /// The semantic embedding vector for fuzzy recall.
    pub vector: Option<Vec<f32>>,
}

/// A value stored in an assertion object.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub enum ObjectValue {
    /// A text string value.
    Text(String),
    /// A numeric value (float).
    Number(f64),
    /// A boolean value.
    Boolean(bool),
    /// A reference to another entity (pointer).
    Reference(EntityId),
}

/// A cryptographic signature from an agent.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct SignatureEntry {
    /// The Ed25519 Public Key of the agent.
    pub agent_id: [u8; 32],
    /// The Ed25519 Signature of the assertion.
    pub signature: [u8; 64],
    /// The timestamp when the agent signed this assertion.
    pub timestamp: u64,
    /// Signature version: 1 = signs "{subject}:{predicate}", 2 = signs content hash.
    ///
    /// Version 2 (enterprise-grade) signs the BLAKE3 hash of the full serialized
    /// assertion (without signatures), protecting all fields from tampering.
    /// Version 1 (legacy) only signs subject:predicate, leaving other fields unprotected.
    pub version: u8,
}
