//! Specialized storage for TrustRank reputation scores.
//!
//! The TrustRank system tracks per-agent reputation scores that affect how
//! their assertions are weighted in the Authority lens. This is the foundation
//! of "The Hive" learning loop.
//!
//! # Storage Layout
//!
//! | Key Pattern | Value | Purpose |
//! |-------------|-------|---------|
//! | `TR:{agent_id}` | Serialized TrustRank | Agent reputation data |
//!
//! # Design Philosophy
//!
//! This module follows the "Deep Module" principle from Philosophy of Software Design:
//! - Simple interface hiding complex reputation tracking
//! - Content-addressed agent IDs (public keys)
//! - Decay mechanics for confidence half-life
//! - Learning loop integration for accuracy tracking
//!
//! All operations are defensive against missing data (new agents start at default score).

#[cfg(test)]
mod basic_tests;
#[cfg(test)]
mod gold_standard_tests;
mod model;
mod store_impl;

pub use model::*;
pub use store_impl::*;

use crate::error::Result;
use async_trait::async_trait;
use std::sync::Arc;

/// Specialized storage trait for TrustRank operations.
///
/// This trait provides reputation-specific operations on top of a generic KVStore,
/// enabling efficient trust score management for The Hive learning loop.
///
/// # Example
///
/// ```ignore
/// let trust_store = GenericTrustRankStore::new(kv_store);
/// let trust = trust_store.get_trust_rank(&agent_id).await?;
/// trust_store.update_trust_rank(&agent_id, 0.1, timestamp).await?;
/// ```
#[async_trait]
pub trait TrustRankStore: Send + Sync {
    /// Get the TrustRank for an agent.
    ///
    /// If the agent has no stored TrustRank, returns a new default instance.
    ///
    /// # Arguments
    /// * `agent_id` - The agent's Ed25519 public key
    ///
    /// # Returns
    /// The agent's TrustRank, or a default instance for new agents
    async fn get_trust_rank(&self, agent_id: &[u8; 32]) -> Result<TrustRank>;

    /// Update an agent's TrustRank score by a delta.
    ///
    /// This operation:
    /// 1. Loads current TrustRank (or creates default)
    /// 2. Applies the delta adjustment
    /// 3. Stores the updated TrustRank
    ///
    /// # Arguments
    /// * `agent_id` - The agent's Ed25519 public key
    /// * `delta` - Amount to add to the score (can be negative)
    /// * `timestamp` - Unix timestamp of this update
    ///
    /// # Returns
    /// The new score after update
    async fn update_trust_rank(
        &self,
        agent_id: &[u8; 32],
        delta: f32,
        timestamp: u64,
    ) -> Result<f32>;

    /// Apply confidence half-life decay to all stored TrustRanks.
    ///
    /// Scans all TrustRank entries and applies decay based on elapsed time.
    /// This should be run periodically (e.g., daily) to decay stale reputations.
    ///
    /// # Arguments
    /// * `current_timestamp` - Current Unix timestamp in seconds
    /// * `half_life_seconds` - Half-life duration (default: 30 days)
    ///
    /// # Returns
    /// Number of TrustRanks that were decayed
    async fn decay_trust_ranks(
        &self,
        current_timestamp: u64,
        half_life_seconds: Option<u64>,
    ) -> Result<usize>;

    /// Record an assertion outcome for learning loop tracking.
    ///
    /// Updates the agent's accuracy metrics and adjusts their score based on
    /// the outcome. Accurate predictions increase reputation, inaccurate ones decrease it.
    ///
    /// # Arguments
    /// * `agent_id` - The agent's Ed25519 public key
    /// * `was_accurate` - Whether the assertion was correct
    /// * `timestamp` - Unix timestamp of this outcome
    ///
    /// # Returns
    /// The new trust score after recording the outcome
    async fn record_outcome(
        &self,
        agent_id: &[u8; 32],
        was_accurate: bool,
        timestamp: u64,
    ) -> Result<f32>;

    /// Store a TrustRank directly (for testing or batch operations).
    ///
    /// # Arguments
    /// * `trust_rank` - The TrustRank to store
    async fn put_trust_rank(&self, trust_rank: &TrustRank) -> Result<()>;

    /// Verify an agent's answer against a gold standard.
    ///
    /// This method checks if the agent's answer matches the gold standard's
    /// expected object. If it matches, the agent is rewarded with increased
    /// TrustRank. If it doesn't match, the agent is penalized.
    ///
    /// Rewards: +0.05 trust per correct alignment (capped at 1.0)
    /// Penalties: -0.1 trust per incorrect alignment (floored at 0.0)
    ///
    /// The outcome is also recorded for accuracy tracking.
    ///
    /// # Arguments
    /// * `agent_id` - The agent's Ed25519 public key
    /// * `agent_object` - The agent's proposed answer
    /// * `gold_standard` - The gold standard to verify against
    /// * `timestamp` - Unix timestamp of this verification
    ///
    /// # Returns
    /// The trust adjustment that was applied (Rewarded or Penalized)
    async fn verify_agent_against_gold_standard(
        &self,
        agent_id: &[u8; 32],
        agent_object: &str,
        gold_standard: &stemedb_core::types::GoldStandard,
        timestamp: u64,
    ) -> Result<model::TrustAdjustment>;
}

// Blanket implementation for Arc<T> where T: TrustRankStore
// This enables sharing TrustRankStore across threads and components.
#[async_trait]
impl<T: TrustRankStore + ?Sized> TrustRankStore for Arc<T> {
    async fn get_trust_rank(&self, agent_id: &[u8; 32]) -> Result<TrustRank> {
        (**self).get_trust_rank(agent_id).await
    }

    async fn update_trust_rank(
        &self,
        agent_id: &[u8; 32],
        delta: f32,
        timestamp: u64,
    ) -> Result<f32> {
        (**self).update_trust_rank(agent_id, delta, timestamp).await
    }

    async fn decay_trust_ranks(
        &self,
        current_timestamp: u64,
        half_life_seconds: Option<u64>,
    ) -> Result<usize> {
        (**self).decay_trust_ranks(current_timestamp, half_life_seconds).await
    }

    async fn record_outcome(
        &self,
        agent_id: &[u8; 32],
        was_accurate: bool,
        timestamp: u64,
    ) -> Result<f32> {
        (**self).record_outcome(agent_id, was_accurate, timestamp).await
    }

    async fn put_trust_rank(&self, trust_rank: &TrustRank) -> Result<()> {
        (**self).put_trust_rank(trust_rank).await
    }

    async fn verify_agent_against_gold_standard(
        &self,
        agent_id: &[u8; 32],
        agent_object: &str,
        gold_standard: &stemedb_core::types::GoldStandard,
        timestamp: u64,
    ) -> Result<model::TrustAdjustment> {
        (**self)
            .verify_agent_against_gold_standard(agent_id, agent_object, gold_standard, timestamp)
            .await
    }
}
