//! Parsed `VerifiedPersona` credential type.

use serde::{Deserialize, Serialize};

use crate::error::LastIDError;
use crate::types::VerifiedCredential;

/// Parsed `LastID.VerifiedPersona` credential with typed fields.
///
/// # Example
///
/// ```rust,ignore
/// use lastid_sdk::types::parsed::ParsedVerifiedPersona;
///
/// let persona = ParsedVerifiedPersona::try_from(&credential)?;
/// if let Some(level) = &persona.verification_level {
///     println!("Verification level: {}", level);
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct ParsedVerifiedPersona {
    /// Display name.
    pub display_name: Option<String>,
    /// Given (first) name.
    pub given_name: Option<String>,
    /// Family (last) name.
    pub family_name: Option<String>,
    /// Email address.
    pub email: Option<String>,
    /// Phone number.
    pub phone: Option<String>,
    /// Verification level (e.g., "basic", "enhanced").
    pub verification_level: Option<String>,
    /// Timestamp when verification occurred (Unix epoch seconds).
    pub verified_at: Option<i64>,
}

impl TryFrom<&VerifiedCredential> for ParsedVerifiedPersona {
    type Error = LastIDError;

    fn try_from(cred: &VerifiedCredential) -> Result<Self, Self::Error> {
        if cred.credential_type != "LastID.VerifiedPersona" {
            return Err(LastIDError::invalid_credential(format!(
                "Expected LastID.VerifiedPersona, got {}",
                cred.credential_type
            )));
        }

        Ok(Self {
            display_name: cred.get_claim_str("display_name").map(String::from),
            given_name: cred.get_claim_str("given_name").map(String::from),
            family_name: cred.get_claim_str("family_name").map(String::from),
            email: cred.get_claim_str("email").map(String::from),
            phone: cred.get_claim_str("phone").map(String::from),
            verification_level: cred.get_claim_str("verification_level").map(String::from),
            verified_at: cred.get_claim_i64("verified_at"),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::trust_registry::IssuerStatus;
    use chrono::Utc;

    fn test_credential(cred_type: &str, claims: serde_json::Value) -> VerifiedCredential {
        VerifiedCredential {
            subject_did: "did:lastid:user123".into(),
            issuer_did: "did:lastid:issuer456".into(),
            credential_type: cred_type.into(),
            claims,
            issued_at: Utc::now(),
            expires_at: Utc::now() + chrono::Duration::hours(24),
            issuer_status: IssuerStatus::Authorized,
            signature_verified: true,
        }
    }

    #[test]
    fn test_parse_verified_persona() {
        let cred = test_credential(
            "LastID.VerifiedPersona",
            serde_json::json!({
                "display_name": "John Doe",
                "given_name": "John",
                "family_name": "Doe",
                "verification_level": "enhanced"
            }),
        );

        let persona = ParsedVerifiedPersona::try_from(&cred).unwrap();
        assert_eq!(persona.display_name, Some("John Doe".to_string()));
        assert_eq!(persona.given_name, Some("John".to_string()));
        assert_eq!(persona.family_name, Some("Doe".to_string()));
        assert_eq!(persona.verification_level, Some("enhanced".to_string()));
    }

    #[test]
    fn test_parse_verified_persona_wrong_type() {
        let cred = test_credential("LastID.Persona", serde_json::json!({}));

        let result = ParsedVerifiedPersona::try_from(&cred);
        assert!(result.is_err());
    }
}
