//! Parsed `AgeProof` credential type.

use serde::{Deserialize, Serialize};

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

/// Parsed `LastID.AgeProof` credential with typed fields.
///
/// # Example
///
/// ```rust,ignore
/// use lastid_sdk::types::parsed::ParsedAgeProof;
///
/// let age_proof = ParsedAgeProof::try_from(&credential)?;
/// if age_proof.age_verified {
///     println!("Age verified!");
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct ParsedAgeProof {
    /// Actual age (if disclosed).
    pub age: Option<i64>,
    /// Whether age was verified.
    pub age_verified: bool,
    /// Date when verification occurred.
    pub verification_date: Option<String>,
    /// The minimum age threshold that was verified (e.g., 18, 21).
    pub minimum_age_met: Option<i64>,
}

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

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

        Ok(Self {
            age: cred.get_claim_i64("age"),
            age_verified: cred.get_claim_bool("age_verified").unwrap_or(false),
            verification_date: cred.get_claim_str("verification_date").map(String::from),
            minimum_age_met: cred.get_claim_i64("minimum_age_met"),
        })
    }
}

#[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_age_proof() {
        let cred = test_credential(
            "LastID.AgeProof",
            serde_json::json!({
                "age_verified": true,
                "minimum_age_met": 21
            }),
        );

        let age_proof = ParsedAgeProof::try_from(&cred).unwrap();
        assert!(age_proof.age_verified);
        assert_eq!(age_proof.minimum_age_met, Some(21));
        assert!(age_proof.age.is_none()); // Age not disclosed
    }

    #[test]
    fn test_parse_age_proof_with_age() {
        let cred = test_credential(
            "LastID.AgeProof",
            serde_json::json!({
                "age": 25,
                "age_verified": true
            }),
        );

        let age_proof = ParsedAgeProof::try_from(&cred).unwrap();
        assert_eq!(age_proof.age, Some(25));
        assert!(age_proof.age_verified);
    }

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

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