//! Specialized storage for EigenTrust trust graph.
//!
//! The TrustGraphStore provides a web of trust where agents can express
//! trust in other agents. This trust graph is used to compute global
//! EigenTrust scores that are Sybil-resistant.
//!
//! # Storage Layout
//!
//! | Key Pattern | Value | Purpose |
//! |-------------|-------|---------|
//! | `\x00TG:{from}:{to}` | Serialized TrustEdge | Trust edge (forward) |
//! | `\x00TGR:{to}:{from}` | Serialized TrustEdge | Trust edge (reverse index) |
//! | `\x00ET:state` | Serialized EigenTrustState | Computed global scores |
//! | `\x00ET:seed:{agent}` | f32 bytes | Seed trust for pre-trusted agents |
//!
//! # Sybil Resistance
//!
//! The EigenTrust algorithm ensures that isolated rings of colluding agents
//! cannot accumulate trust. Only agents connected to pre-trusted seeds
//! can gain meaningful reputation.

mod eigentrust;
mod model;
mod store_impl;
#[cfg(test)]
mod store_tests;

pub use eigentrust::compute_eigentrust_scores;
pub use model::*;
pub use store_impl::*;

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

/// Specialized storage trait for TrustGraph operations.
///
/// This trait provides trust graph management for the EigenTrust system,
/// enabling Sybil-resistant reputation across the network.
///
/// # Example
///
/// ```ignore
/// let trust_store = GenericTrustGraphStore::new(kv_store);
///
/// // Add trust relationship
/// let edge = TrustEdge::new(agent_a, agent_b, 0.8, timestamp, None);
/// trust_store.add_trust_edge(&edge).await?;
///
/// // Compute EigenTrust scores
/// let state = trust_store.compute_eigentrust(&EigenTrustConfig::default()).await?;
///
/// // Query score
/// let score = trust_store.get_eigentrust_score(&agent_b).await?;
/// ```
#[async_trait]
pub trait TrustGraphStore: Send + Sync {
    // ── Edge CRUD ────────────────────────────────────────────────────────

    /// Add or update a trust edge in the graph.
    ///
    /// This creates both the forward index (`TG:{from}:{to}`) and
    /// reverse index (`TGR:{to}:{from}`) for efficient bidirectional queries.
    ///
    /// # Arguments
    /// * `edge` - The trust edge to add
    async fn add_trust_edge(&self, edge: &TrustEdge) -> Result<()>;

    /// Remove a trust edge from the graph.
    ///
    /// # Arguments
    /// * `from` - Agent granting trust
    /// * `to` - Agent receiving trust
    ///
    /// # Returns
    /// `true` if the edge existed and was removed, `false` if not found
    async fn remove_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<bool>;

    /// Get a specific trust edge.
    ///
    /// # Arguments
    /// * `from` - Agent granting trust
    /// * `to` - Agent receiving trust
    ///
    /// # Returns
    /// The trust edge if it exists
    async fn get_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<Option<TrustEdge>>;

    // ── Graph traversal ──────────────────────────────────────────────────

    /// Get all outgoing trust edges from an agent.
    ///
    /// Returns (to_agent, weight) pairs for agents that this agent trusts.
    ///
    /// # Arguments
    /// * `from` - Agent granting trust
    async fn get_trusts(&self, from: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>>;

    /// Get all incoming trust edges to an agent.
    ///
    /// Returns (from_agent, weight) pairs for agents that trust this agent.
    /// Uses the reverse index for efficient queries.
    ///
    /// # Arguments
    /// * `to` - Agent receiving trust
    async fn get_trusted_by(&self, to: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>>;

    /// Get all edges in the trust graph.
    ///
    /// Used by the EigenTrust computation. May be expensive for large graphs.
    async fn get_all_edges(&self) -> Result<Vec<TrustEdge>>;

    // ── Seed trust ───────────────────────────────────────────────────────

    /// Set seed trust for a pre-trusted agent.
    ///
    /// Seed trust defines the "P" vector in EigenTrust. These are agents
    /// that are pre-trusted (e.g., verified organizations, system admins).
    ///
    /// # Arguments
    /// * `agent` - Agent to pre-trust
    /// * `trust` - Seed trust weight (0.0 to 1.0)
    async fn set_seed_trust(&self, agent: &[u8; 32], trust: f32) -> Result<()>;

    /// Get seed trust for an agent.
    ///
    /// Returns 0.0 if the agent has no seed trust.
    async fn get_seed_trust(&self, agent: &[u8; 32]) -> Result<f32>;

    /// Get all seed trust entries.
    ///
    /// Used by the EigenTrust computation to build the P vector.
    async fn get_all_seed_trust(&self) -> Result<Vec<([u8; 32], f32)>>;

    /// Remove seed trust for an agent.
    async fn remove_seed_trust(&self, agent: &[u8; 32]) -> Result<bool>;

    // ── EigenTrust computation ───────────────────────────────────────────

    /// Compute EigenTrust scores for all agents in the graph.
    ///
    /// This runs the power iteration algorithm and stores the result.
    /// Should be called periodically (e.g., daily) to update global scores.
    ///
    /// # Arguments
    /// * `config` - Algorithm configuration
    ///
    /// # Returns
    /// The computed state
    async fn compute_eigentrust(&self, config: &EigenTrustConfig) -> Result<EigenTrustState>;

    /// Get the current EigenTrust state (previously computed scores).
    ///
    /// Returns `None` if EigenTrust has never been computed.
    async fn get_eigentrust_state(&self) -> Result<Option<EigenTrustState>>;

    /// Get the EigenTrust score for a specific agent.
    ///
    /// Returns 0.0 if:
    /// - The agent is not in the graph
    /// - EigenTrust has never been computed
    async fn get_eigentrust_score(&self, agent: &[u8; 32]) -> Result<f32>;
}

// Blanket implementation for Arc<T> where T: TrustGraphStore
#[async_trait]
impl<T: TrustGraphStore + ?Sized> TrustGraphStore for Arc<T> {
    async fn add_trust_edge(&self, edge: &TrustEdge) -> Result<()> {
        (**self).add_trust_edge(edge).await
    }

    async fn remove_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<bool> {
        (**self).remove_trust_edge(from, to).await
    }

    async fn get_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<Option<TrustEdge>> {
        (**self).get_trust_edge(from, to).await
    }

    async fn get_trusts(&self, from: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>> {
        (**self).get_trusts(from).await
    }

    async fn get_trusted_by(&self, to: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>> {
        (**self).get_trusted_by(to).await
    }

    async fn get_all_edges(&self) -> Result<Vec<TrustEdge>> {
        (**self).get_all_edges().await
    }

    async fn set_seed_trust(&self, agent: &[u8; 32], trust: f32) -> Result<()> {
        (**self).set_seed_trust(agent, trust).await
    }

    async fn get_seed_trust(&self, agent: &[u8; 32]) -> Result<f32> {
        (**self).get_seed_trust(agent).await
    }

    async fn get_all_seed_trust(&self) -> Result<Vec<([u8; 32], f32)>> {
        (**self).get_all_seed_trust().await
    }

    async fn remove_seed_trust(&self, agent: &[u8; 32]) -> Result<bool> {
        (**self).remove_seed_trust(agent).await
    }

    async fn compute_eigentrust(&self, config: &EigenTrustConfig) -> Result<EigenTrustState> {
        (**self).compute_eigentrust(config).await
    }

    async fn get_eigentrust_state(&self) -> Result<Option<EigenTrustState>> {
        (**self).get_eigentrust_state().await
    }

    async fn get_eigentrust_score(&self, agent: &[u8; 32]) -> Result<f32> {
        (**self).get_eigentrust_score(agent).await
    }
}
