//! Specialized storage for domain-specific trust tracking.
//!
//! The DomainTrustStore tracks per-agent expertise within specific domains.
//! This enables fine-grained trust: an agent can be highly trusted in medicine
//! but untrusted in finance.
//!
//! # Storage Layout
//!
//! | Key Pattern | Value | Purpose |
//! |-------------|-------|---------|
//! | `\x00DT:{agent}:{domain}` | Serialized DomainTrust | Domain-specific trust |
//!
//! # Use Case
//!
//! Combined with EigenTrust, domain trust enables weighted resolution:
//! ```text
//! effective_weight = confidence × eigentrust_score × domain_factor
//! ```
//!
//! This ensures that an agent's assertions are weighted by both their
//! global reputation AND their domain-specific expertise.

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 DomainTrust operations.
///
/// This trait provides domain-specific trust tracking for agents,
/// enabling expertise-weighted assertion resolution.
///
/// # Example
///
/// ```ignore
/// let domain_store = GenericDomainTrustStore::new(kv_store);
///
/// // Record domain-specific outcome
/// let score = domain_store.record_domain_outcome(
///     &agent_id,
///     "treats_condition",  // Domain auto-extracted
///     true,                // Was accurate
///     timestamp,
/// ).await?;
///
/// // Get effective trust (eigentrust × domain factor)
/// let effective = domain_store.get_effective_trust(
///     &agent_id,
///     "treats_condition",
///     eigentrust_score,
/// ).await?;
/// ```
#[async_trait]
pub trait DomainTrustStore: Send + Sync {
    /// Get the domain trust for an agent in a specific domain.
    ///
    /// Returns a default DomainTrust (score 0.5) if not found.
    ///
    /// # Arguments
    /// * `agent` - Agent's Ed25519 public key
    /// * `domain` - Domain name (e.g., "medicine", "finance")
    async fn get_domain_trust(&self, agent: &[u8; 32], domain: &str) -> Result<DomainTrust>;

    /// Get all domain trust entries for an agent.
    ///
    /// Returns all domains the agent has records in.
    async fn get_all_domains_for_agent(&self, agent: &[u8; 32]) -> Result<Vec<DomainTrust>>;

    /// Record a domain-specific outcome.
    ///
    /// This method:
    /// 1. Extracts the domain from the predicate
    /// 2. Loads or creates the DomainTrust for (agent, domain)
    /// 3. Updates accuracy tracking
    /// 4. Adjusts the domain score
    /// 5. Stores the updated DomainTrust
    ///
    /// # Arguments
    /// * `agent` - Agent's Ed25519 public key
    /// * `predicate` - The assertion predicate (domain auto-extracted)
    /// * `was_accurate` - Whether the assertion was correct
    /// * `timestamp` - Unix timestamp
    ///
    /// # Returns
    /// The new domain score after update
    async fn record_domain_outcome(
        &self,
        agent: &[u8; 32],
        predicate: &str,
        was_accurate: bool,
        timestamp: u64,
    ) -> Result<f32>;

    /// Store a DomainTrust directly (for testing or batch operations).
    async fn put_domain_trust(&self, dt: &DomainTrust) -> Result<()>;

    /// Calculate effective trust for an assertion.
    ///
    /// Combines the global EigenTrust score with domain-specific expertise:
    /// ```text
    /// effective_trust = eigentrust_score × domain_factor(domain_score)
    /// ```
    ///
    /// # Arguments
    /// * `agent` - Agent's Ed25519 public key
    /// * `predicate` - The assertion predicate (domain auto-extracted)
    /// * `eigentrust_score` - The agent's global EigenTrust score
    ///
    /// # Returns
    /// The effective trust score for this agent in this domain
    async fn get_effective_trust(
        &self,
        agent: &[u8; 32],
        predicate: &str,
        eigentrust_score: f32,
    ) -> Result<f32>;
}

// Blanket implementation for Arc<T> where T: DomainTrustStore
#[async_trait]
impl<T: DomainTrustStore + ?Sized> DomainTrustStore for Arc<T> {
    async fn get_domain_trust(&self, agent: &[u8; 32], domain: &str) -> Result<DomainTrust> {
        (**self).get_domain_trust(agent, domain).await
    }

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

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

    async fn put_domain_trust(&self, dt: &DomainTrust) -> Result<()> {
        (**self).put_domain_trust(dt).await
    }

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