//! Response DTOs from StemeDB API queries.

use serde::{Deserialize, Serialize};

use super::enums::{LifecycleDto, ObjectValueDto, SignatureDto, SourceClassDto};

/// Response from creating an assertion.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateResponse {
    /// Content-addressed hash of the created assertion (hex-encoded)
    pub hash: String,

    /// Status message
    pub status: String,
}

/// Response containing a single assertion.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssertionDto {
    /// Content-addressed hash of this assertion (hex-encoded)
    pub hash: String,

    /// The subject entity
    pub subject: String,

    /// The predicate/relation
    pub predicate: String,

    /// The object value
    pub object: ObjectValueDto,

    /// Hash of parent assertion (hex-encoded, optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub parent_hash: Option<String>,

    /// Hash of source evidence (hex-encoded)
    pub source_hash: String,

    /// Source authority tier
    pub source_class: SourceClassDto,

    /// Perceptual hash for visual anchoring (hex-encoded, optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub visual_hash: Option<String>,

    /// Epoch ID (hex-encoded, optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub epoch: Option<String>,

    /// Lifecycle stage
    pub lifecycle: LifecycleDto,

    /// Agent signatures
    pub signatures: Vec<SignatureDto>,

    /// Confidence score (0.0 to 1.0)
    pub confidence: f32,

    /// Creation timestamp (Unix epoch)
    pub timestamp: u64,

    /// Semantic embedding vector (optional)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vector: Option<Vec<f32>>,

    /// Structured source metadata as a JSON string (optional).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source_metadata: Option<String>,
}

/// Response from a query operation.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryResponse {
    /// Matching assertions
    pub assertions: Vec<AssertionDto>,

    /// Total number of results returned
    pub total_count: usize,

    /// Whether there are more results beyond the limit
    pub has_more: bool,

    /// Conflict score (0.0 = unanimous, 1.0 = max conflict).
    /// Only present when a lens is applied.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub conflict_score: Option<f32>,

    /// Confidence in the resolution (0.0 to 1.0).
    /// Only present when a lens is applied.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub resolution_confidence: Option<f32>,
}

/// Per-tier resolution result from LayeredConsensus lens.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TierResolutionDto {
    /// The tier number (0-5). Lower = higher authority.
    pub tier: u8,

    /// The source class for this tier.
    pub source_class: SourceClassDto,

    /// The winning assertion from within-tier consensus, if any candidates.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub winner: Option<AssertionDto>,

    /// Number of candidates in this tier.
    pub candidates_count: usize,

    /// Within-tier conflict score (0.0 = unanimous, 1.0 = max conflict).
    pub conflict_score: f32,

    /// Within-tier resolution confidence (0.0 to 1.0).
    pub resolution_confidence: f32,
}

/// Response from a LayeredConsensus query.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LayeredResponse {
    /// The subject that was queried.
    pub subject: String,

    /// The predicate that was queried.
    pub predicate: String,

    /// Per-tier consensus results, ordered by tier (0 = highest authority first).
    pub tiers: Vec<TierResolutionDto>,

    /// Overall winner: winner from the highest-authority tier that has candidates.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub overall_winner: Option<AssertionDto>,

    /// Cross-tier disagreement score (0.0 = tiers agree, 1.0 = tiers disagree).
    pub overall_conflict_score: f32,

    /// Total candidates considered across all tiers.
    pub total_candidates: usize,

    /// Unix timestamp when this view was computed.
    pub computed_at: u64,

    /// Which lens was used (always "LayeredConsensus").
    pub lens_name: String,
}
