//! Trust tiers for graduated admission control.
//!
//! Trust tiers map an agent's reputation score (0.0-1.0) to specific quotas
//! and proof-of-work requirements. This graduated system allows new agents
//! to earn trust over time while protecting the system from spam and Sybil attacks.
//!
//! # Tier Boundaries
//!
//! | Trust Range | Tier       | Quota Multiplier | PoW Required |
//! |-------------|------------|------------------|--------------|
//! | 0.0-0.3     | Untrusted  | 0.1x (1,000/hr)  | Yes          |
//! | 0.3-0.5     | Limited    | 0.5x (5,000/hr)  | Yes          |
//! | 0.5-0.7     | Verified   | 1.0x (10,000/hr) | No           |
//! | 0.7-0.9     | Trusted    | 2.0x (20,000/hr) | No           |
//! | 0.9-1.0     | Authority  | 10.0x (100k/hr)  | No           |

/// Base quota limit per hour (10,000 tokens).
/// Tiers apply multipliers to this base.
pub const BASE_QUOTA_LIMIT: u64 = 10_000;

/// Trust score threshold above which PoW is exempt.
/// Agents with trust >= this value skip proof-of-work regardless of tier.
pub const TRUST_POW_EXEMPTION_THRESHOLD: f32 = 0.6;

/// Trust tier classification based on reputation score.
///
/// Each tier determines:
/// - Quota multiplier: How many tokens per hour the agent can use
/// - PoW requirement: Whether proof-of-work is needed for submissions
///
/// New agents start at `Untrusted` (0.5 score, which is actually Verified tier).
/// They can improve by making accurate assertions verified against gold standards.
#[derive(
    Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize,
)]
#[archive(check_bytes)]
pub enum TrustTier {
    /// Untrusted tier: 0.0-0.3 trust score.
    /// 0.1x quota multiplier (1,000 tokens/hr), PoW required.
    Untrusted,

    /// Limited tier: 0.3-0.5 trust score.
    /// 0.5x quota multiplier (5,000 tokens/hr), PoW required.
    Limited,

    /// Verified tier: 0.5-0.7 trust score.
    /// 1.0x quota multiplier (10,000 tokens/hr), PoW exempt.
    Verified,

    /// Trusted tier: 0.7-0.9 trust score.
    /// 2.0x quota multiplier (20,000 tokens/hr), PoW exempt.
    Trusted,

    /// Authority tier: 0.9-1.0 trust score.
    /// 10.0x quota multiplier (100,000 tokens/hr), PoW exempt.
    Authority,
}

impl TrustTier {
    /// Determine trust tier from a reputation score.
    ///
    /// # Arguments
    /// * `score` - Trust score in range [0.0, 1.0]
    ///
    /// # Returns
    /// The appropriate tier for the given score.
    ///
    /// # Example
    /// ```
    /// use stemedb_core::types::TrustTier;
    ///
    /// assert_eq!(TrustTier::from_score(0.1), TrustTier::Untrusted);
    /// assert_eq!(TrustTier::from_score(0.5), TrustTier::Verified);
    /// assert_eq!(TrustTier::from_score(0.95), TrustTier::Authority);
    /// ```
    #[must_use]
    pub fn from_score(score: f32) -> Self {
        // Clamp to valid range
        let score = score.clamp(0.0, 1.0);

        if score >= 0.9 {
            TrustTier::Authority
        } else if score >= 0.7 {
            TrustTier::Trusted
        } else if score >= 0.5 {
            TrustTier::Verified
        } else if score >= 0.3 {
            TrustTier::Limited
        } else {
            TrustTier::Untrusted
        }
    }

    /// Get the quota multiplier for this tier.
    ///
    /// The multiplier is applied to the base quota (10,000 tokens/hr):
    /// - Untrusted: 0.1x = 1,000/hr
    /// - Limited: 0.5x = 5,000/hr
    /// - Verified: 1.0x = 10,000/hr
    /// - Trusted: 2.0x = 20,000/hr
    /// - Authority: 10.0x = 100,000/hr
    #[must_use]
    pub fn quota_multiplier(&self) -> f32 {
        match self {
            TrustTier::Untrusted => 0.1,
            TrustTier::Limited => 0.5,
            TrustTier::Verified => 1.0,
            TrustTier::Trusted => 2.0,
            TrustTier::Authority => 10.0,
        }
    }

    /// Get the effective quota limit for this tier.
    ///
    /// # Returns
    /// The per-hour quota limit (base * multiplier).
    #[must_use]
    pub fn effective_quota_limit(&self) -> u64 {
        (BASE_QUOTA_LIMIT as f32 * self.quota_multiplier()) as u64
    }

    /// Check if this tier requires proof-of-work.
    ///
    /// Only `Untrusted` and `Limited` tiers require PoW.
    /// Note: Agents with 50+ assertions are exempt regardless of tier.
    #[must_use]
    pub fn requires_pow(&self) -> bool {
        matches!(self, TrustTier::Untrusted | TrustTier::Limited)
    }

    /// Get human-readable name for this tier.
    #[must_use]
    pub fn name(&self) -> &'static str {
        match self {
            TrustTier::Untrusted => "Untrusted",
            TrustTier::Limited => "Limited",
            TrustTier::Verified => "Verified",
            TrustTier::Trusted => "Trusted",
            TrustTier::Authority => "Authority",
        }
    }

    /// Get the trust score lower bound for this tier.
    #[must_use]
    pub fn min_score(&self) -> f32 {
        match self {
            TrustTier::Untrusted => 0.0,
            TrustTier::Limited => 0.3,
            TrustTier::Verified => 0.5,
            TrustTier::Trusted => 0.7,
            TrustTier::Authority => 0.9,
        }
    }

    /// Get the trust score upper bound for this tier (exclusive).
    #[must_use]
    pub fn max_score(&self) -> f32 {
        match self {
            TrustTier::Untrusted => 0.3,
            TrustTier::Limited => 0.5,
            TrustTier::Verified => 0.7,
            TrustTier::Trusted => 0.9,
            TrustTier::Authority => 1.0,
        }
    }
}

impl std::fmt::Display for TrustTier {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.name())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_from_score_boundaries() {
        // Untrusted: 0.0-0.3
        assert_eq!(TrustTier::from_score(0.0), TrustTier::Untrusted);
        assert_eq!(TrustTier::from_score(0.1), TrustTier::Untrusted);
        assert_eq!(TrustTier::from_score(0.29), TrustTier::Untrusted);

        // Limited: 0.3-0.5
        assert_eq!(TrustTier::from_score(0.3), TrustTier::Limited);
        assert_eq!(TrustTier::from_score(0.4), TrustTier::Limited);
        assert_eq!(TrustTier::from_score(0.49), TrustTier::Limited);

        // Verified: 0.5-0.7
        assert_eq!(TrustTier::from_score(0.5), TrustTier::Verified);
        assert_eq!(TrustTier::from_score(0.6), TrustTier::Verified);
        assert_eq!(TrustTier::from_score(0.69), TrustTier::Verified);

        // Trusted: 0.7-0.9
        assert_eq!(TrustTier::from_score(0.7), TrustTier::Trusted);
        assert_eq!(TrustTier::from_score(0.8), TrustTier::Trusted);
        assert_eq!(TrustTier::from_score(0.89), TrustTier::Trusted);

        // Authority: 0.9-1.0
        assert_eq!(TrustTier::from_score(0.9), TrustTier::Authority);
        assert_eq!(TrustTier::from_score(0.95), TrustTier::Authority);
        assert_eq!(TrustTier::from_score(1.0), TrustTier::Authority);
    }

    #[test]
    fn test_from_score_clamping() {
        // Out of range values should be clamped
        assert_eq!(TrustTier::from_score(-0.5), TrustTier::Untrusted);
        assert_eq!(TrustTier::from_score(1.5), TrustTier::Authority);
    }

    #[test]
    fn test_quota_multipliers() {
        assert!((TrustTier::Untrusted.quota_multiplier() - 0.1).abs() < f32::EPSILON);
        assert!((TrustTier::Limited.quota_multiplier() - 0.5).abs() < f32::EPSILON);
        assert!((TrustTier::Verified.quota_multiplier() - 1.0).abs() < f32::EPSILON);
        assert!((TrustTier::Trusted.quota_multiplier() - 2.0).abs() < f32::EPSILON);
        assert!((TrustTier::Authority.quota_multiplier() - 10.0).abs() < f32::EPSILON);
    }

    #[test]
    fn test_effective_quota_limits() {
        assert_eq!(TrustTier::Untrusted.effective_quota_limit(), 1_000);
        assert_eq!(TrustTier::Limited.effective_quota_limit(), 5_000);
        assert_eq!(TrustTier::Verified.effective_quota_limit(), 10_000);
        assert_eq!(TrustTier::Trusted.effective_quota_limit(), 20_000);
        assert_eq!(TrustTier::Authority.effective_quota_limit(), 100_000);
    }

    #[test]
    fn test_requires_pow() {
        assert!(TrustTier::Untrusted.requires_pow());
        assert!(TrustTier::Limited.requires_pow());
        assert!(!TrustTier::Verified.requires_pow());
        assert!(!TrustTier::Trusted.requires_pow());
        assert!(!TrustTier::Authority.requires_pow());
    }

    #[test]
    fn test_score_ranges() {
        // Verify min/max scores don't overlap incorrectly
        assert!(TrustTier::Untrusted.max_score() <= TrustTier::Limited.min_score() + f32::EPSILON);
        assert!(TrustTier::Limited.max_score() <= TrustTier::Verified.min_score() + f32::EPSILON);
        assert!(TrustTier::Verified.max_score() <= TrustTier::Trusted.min_score() + f32::EPSILON);
        assert!(TrustTier::Trusted.max_score() <= TrustTier::Authority.min_score() + f32::EPSILON);
    }

    #[test]
    fn test_display() {
        assert_eq!(format!("{}", TrustTier::Untrusted), "Untrusted");
        assert_eq!(format!("{}", TrustTier::Authority), "Authority");
    }
}
