//! Conflict analysis data structures for "Trust but Verify".

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

use super::{Hash, PHash};
use crate::types::ObjectValue;

/// Resolution status indicating the level of agreement among claims.
///
/// Used by SkepticLens to communicate whether a fact is settled or disputed.
///
/// # Thresholds
///
/// Based on normalized Shannon entropy of claim weights:
/// - `Unanimous`: entropy < 0.1 (>95% weight on one claim)
/// - `Agreed`: entropy < 0.4 (~75%+ weight on one claim)
/// - `Contested`: entropy >= 0.4 (significant disagreement)
#[derive(Archive, Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq)]
#[archive(check_bytes)]
pub enum ResolutionStatus {
    /// All assertions agree on the same value, or near-zero entropy.
    Unanimous,
    /// Strong majority (>75% weight) agrees on one value.
    Agreed,
    /// No clear consensus; significant disagreement exists.
    Contested,
}

impl ResolutionStatus {
    /// Determine status from conflict score and claim count.
    ///
    /// # Arguments
    /// * `conflict_score` - Normalized Shannon entropy (0.0 to 1.0)
    /// * `claim_count` - Number of distinct claims
    pub fn from_conflict_score(conflict_score: f32, claim_count: usize) -> Self {
        match (conflict_score, claim_count) {
            (_, 0 | 1) => ResolutionStatus::Unanimous,
            (s, _) if s < 0.1 => ResolutionStatus::Unanimous,
            (s, _) if s < 0.4 => ResolutionStatus::Agreed,
            _ => ResolutionStatus::Contested,
        }
    }
}

/// Result of conflict analysis from SkepticLens.
///
/// Unlike `Resolution` which picks a winner, `ConflictAnalysis` maps the
/// entire conflict landscape. It answers: "What are the competing claims
/// and how much do they disagree?"
///
/// # Use Case
///
/// A medical researcher queries "Semaglutide muscle_effect" and gets:
/// - Status: Contested (conflict_score: 0.72)
/// - Claim A: "Significant loss" (45% weight, 12 sources)
/// - Claim B: "Minimal loss" (35% weight, 3 sources)
/// - Claim C: "No effect" (20% weight, 2 sources)
///
/// This enables "Trust but Verify" UX where users see the disagreement.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct ConflictAnalysis {
    /// Overall resolution status (Unanimous, Agreed, Contested).
    pub status: ResolutionStatus,
    /// Conflict score using normalized Shannon entropy.
    /// - 0.0 = unanimous (all weight on one claim)
    /// - 1.0 = maximum chaos (equal weight across all claims)
    pub conflict_score: f32,
    /// All distinct claims, ranked by weight_share descending.
    pub claims: Vec<ClaimSummary>,
    /// Total number of candidate assertions considered.
    pub candidates_count: usize,
}

impl ConflictAnalysis {
    /// Create an empty analysis (no candidates).
    pub fn empty() -> Self {
        Self {
            status: ResolutionStatus::Unanimous,
            conflict_score: 0.0,
            claims: Vec::new(),
            candidates_count: 0,
        }
    }
}

/// Summary of a single claim (unique object value) in the knowledge base.
///
/// Groups all assertions that claim the same value for a subject+predicate,
/// providing aggregate statistics for "Trust but Verify" analysis.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct ClaimSummary {
    /// The claimed value (what this group asserts).
    pub value: ObjectValue,
    /// Normalized weight (0.0 to 1.0) relative to all claims.
    /// This is the claim's share of total support, not confidence in the claim.
    pub weight_share: f32,
    /// Number of assertions making this exact claim.
    pub assertion_count: u32,
    /// Hash of the highest-confidence assertion for this claim (for drill-down).
    pub representative_hash: Hash,
    /// Source provenance for the representative assertion.
    pub source: SourceSummary,
    /// Agents who signed assertions for this claim (for "who said this?").
    pub supporting_agents: Vec<AgentSummary>,
}

/// Minimal source info for provenance ("where did this come from?").
///
/// Enables the "show me the proof" UX where users can trace a claim
/// back to its original source document.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct SourceSummary {
    /// Hash of the source document (PDF, URL, etc.).
    pub source_hash: Hash,
    /// Visual anchor hash for the source (e.g., screenshot of table).
    pub visual_hash: Option<PHash>,
}

/// Minimal agent info for attribution ("who said this?").
///
/// Used in ClaimSummary to show which agents support a particular claim.
#[derive(Archive, Deserialize, Serialize, Debug, Clone, PartialEq)]
#[archive(check_bytes)]
pub struct AgentSummary {
    /// Agent's Ed25519 public key.
    pub agent_id: [u8; 32],
    /// Trust score at query time (from TrustRankStore).
    /// Range: 0.0 (untrusted) to 1.0 (fully trusted).
    pub trust_score: f32,
}
