//! Field verification metadata type for credential claims.
//!
//! This module provides the `FieldVerificationMetadata` struct representing
//! verification details for specific credential fields.

use serde::{Deserialize, Serialize};

/// Verification metadata for a specific credential field.
///
/// Describes how and when a field was verified, including the verification
/// provider, method, and timestamp.
///
/// # Example
///
/// ```rust
/// use lastid_sdk::types::FieldVerificationMetadata;
///
/// let metadata = FieldVerificationMetadata {
///     verified: true,
///     provider: Some("google".to_string()),
///     method: Some("oauth".to_string()),
///     verified_at: Some(1705881600),
/// };
///
/// assert!(metadata.verified);
/// assert_eq!(metadata.provider, Some("google".to_string()));
/// ```
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct FieldVerificationMetadata {
    /// Whether the field value is verified.
    pub verified: bool,

    /// Verification provider (e.g., "google", "twilio", "lastid").
    #[serde(skip_serializing_if = "Option::is_none")]
    pub provider: Option<String>,

    /// Verification method (e.g., "oauth", "sms\_otp", "email\_link").
    #[serde(skip_serializing_if = "Option::is_none")]
    pub method: Option<String>,

    /// Timestamp when verification occurred (Unix epoch seconds).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub verified_at: Option<i64>,
}

impl FieldVerificationMetadata {
    /// Create a new verified field metadata.
    #[must_use]
    pub fn verified() -> Self {
        Self {
            verified: true,
            ..Self::default()
        }
    }

    /// Create a new verified field metadata with provider.
    #[must_use]
    pub fn with_provider(provider: impl Into<String>) -> Self {
        Self {
            verified: true,
            provider: Some(provider.into()),
            method: None,
            verified_at: None,
        }
    }

    /// Check if verification details are available.
    #[must_use]
    pub const fn has_details(&self) -> bool {
        self.provider.is_some() || self.method.is_some() || self.verified_at.is_some()
    }
}

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

    #[test]
    fn test_default() {
        let metadata = FieldVerificationMetadata::default();
        assert!(!metadata.verified);
        assert!(metadata.provider.is_none());
        assert!(metadata.method.is_none());
        assert!(metadata.verified_at.is_none());
    }

    #[test]
    fn test_verified() {
        let metadata = FieldVerificationMetadata::verified();
        assert!(metadata.verified);
        assert!(metadata.provider.is_none());
    }

    #[test]
    fn test_with_provider() {
        let metadata = FieldVerificationMetadata::with_provider("google");
        assert!(metadata.verified);
        assert_eq!(metadata.provider, Some("google".to_string()));
    }

    #[test]
    fn test_has_details() {
        let mut metadata = FieldVerificationMetadata::default();
        assert!(!metadata.has_details());

        metadata.provider = Some("google".to_string());
        assert!(metadata.has_details());

        metadata.provider = None;
        metadata.method = Some("oauth".to_string());
        assert!(metadata.has_details());

        metadata.method = None;
        metadata.verified_at = Some(1705881600);
        assert!(metadata.has_details());
    }

    #[test]
    fn test_serialization() {
        let metadata = FieldVerificationMetadata {
            verified: true,
            provider: Some("twilio".to_string()),
            method: Some("sms_otp".to_string()),
            verified_at: Some(1705881600),
        };

        let json = serde_json::to_string(&metadata).unwrap();
        let deserialized: FieldVerificationMetadata = serde_json::from_str(&json).unwrap();
        assert_eq!(metadata, deserialized);
    }

    #[test]
    fn test_serialization_omits_none() {
        let metadata = FieldVerificationMetadata::verified();
        let json = serde_json::to_string(&metadata).unwrap();

        assert!(!json.contains("provider"));
        assert!(!json.contains("method"));
        assert!(!json.contains("verified_at"));
    }
}
