//! Verified response containing multiple credentials.
//!
//! This module provides the `VerifiedResponse` struct for handling multi-credential
//! presentations, allowing access to individual credentials by type and chain traversal.

use serde::{Deserialize, Serialize};

use super::{DeviceAttestation, DeviceSecurity, FieldVerificationMetadata, VerifiedCredential};

/// Verified response containing multiple credentials from a presentation.
///
/// When a presentation contains multiple credentials (e.g., a chain like
/// Base → Persona → Employment), this struct provides structured access to
/// all credentials and their relationships.
///
/// # Example
///
/// ```rust,ignore
/// use lastid_sdk::types::VerifiedResponse;
///
/// let response: VerifiedResponse = /* from verification */;
///
/// // Iterate over all credentials
/// for cred in response.credentials() {
///     println!("Type: {}", cred.credential_type);
/// }
///
/// // Get a specific credential by type
/// if let Some(persona) = response.credential_by_type("LastID.Persona") {
///     println!("Display name: {:?}", persona.display_name());
/// }
///
/// // Get the primary (leaf) credential
/// let primary = response.primary_credential();
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerifiedResponse {
    /// All verified credentials in the presentation.
    credentials: Vec<VerifiedCredential>,

    /// Shared device attestation (from KB-JWT).
    device_attestation: Option<DeviceAttestation>,

    /// Shared device security context (from KB-JWT).
    device_security: Option<DeviceSecurity>,

    /// Field verification metadata (from KB-JWT).
    field_verification: Option<serde_json::Value>,
}

impl VerifiedResponse {
    /// Create a new `VerifiedResponse` from a list of credentials.
    #[must_use]
    pub const fn new(credentials: Vec<VerifiedCredential>) -> Self {
        Self {
            credentials,
            device_attestation: None,
            device_security: None,
            field_verification: None,
        }
    }

    /// Create a new `VerifiedResponse` with a single credential.
    #[must_use]
    pub fn single(credential: VerifiedCredential) -> Self {
        Self::new(vec![credential])
    }

    /// Create a new `VerifiedResponse` with device attestation.
    #[must_use]
    pub fn with_device_attestation(mut self, attestation: DeviceAttestation) -> Self {
        self.device_attestation = Some(attestation);
        self
    }

    /// Create a new `VerifiedResponse` with device security context.
    #[must_use]
    pub fn with_device_security(mut self, security: DeviceSecurity) -> Self {
        self.device_security = Some(security);
        self
    }

    /// Create a new `VerifiedResponse` with field verification metadata.
    #[must_use]
    pub fn with_field_verification(mut self, verification: serde_json::Value) -> Self {
        self.field_verification = Some(verification);
        self
    }

    // ============================================
    // Credential Access Methods (T047-T049)
    // ============================================

    /// Get an iterator over all credentials in the response.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// for cred in response.credentials() {
    ///     println!("Credential: {}", cred.credential_type);
    /// }
    /// ```
    pub fn credentials(&self) -> impl Iterator<Item = &VerifiedCredential> {
        self.credentials.iter()
    }

    /// Get a credential by its type.
    ///
    /// # Arguments
    ///
    /// * `credential_type` - The credential type (e.g., "LastID.Persona")
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// if let Some(persona) = response.credential_by_type("LastID.Persona") {
    ///     // Access persona claims
    /// }
    /// ```
    #[must_use]
    pub fn credential_by_type(&self, credential_type: &str) -> Option<&VerifiedCredential> {
        self.credentials
            .iter()
            .find(|c| c.credential_type == credential_type)
    }

    /// Get all credentials of a specific type.
    ///
    /// Useful when multiple credentials of the same type may be present.
    #[must_use]
    pub fn credentials_by_type(&self, credential_type: &str) -> Vec<&VerifiedCredential> {
        self.credentials
            .iter()
            .filter(|c| c.credential_type == credential_type)
            .collect()
    }

    /// Get the credential chain in order from root to leaf.
    ///
    /// The chain is ordered based on the standard `LastID` credential hierarchy:
    /// - Base (root)
    /// - Persona / `VerifiedEmail` / `VerifiedPhone`
    /// - `VerifiedPersona`
    /// - Employment / `AgeProof` / Trust
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// for cred in response.credential_chain() {
    ///     println!("Chain: {} -> ", cred.credential_type);
    /// }
    /// ```
    #[must_use]
    pub fn credential_chain(&self) -> Vec<&VerifiedCredential> {
        let type_order = |cred_type: &str| -> usize {
            match cred_type {
                "LastID.Base" => 0,
                "LastID.Persona" | "LastID.VerifiedEmail" | "LastID.VerifiedPhone" => 1,
                "LastID.VerifiedPersona" => 2,
                "LastID.Employment" | "LastID.AgeProof" | "LastID.Trust" => 3,
                _ => 4,
            }
        };

        let mut chain: Vec<_> = self.credentials.iter().collect();
        chain.sort_by_key(|c| type_order(&c.credential_type));
        chain
    }

    /// Get the primary (leaf) credential.
    ///
    /// The primary credential is the "leaf" of the credential chain - the most
    /// specific credential that was requested.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let primary = response.primary_credential();
    /// println!("Primary credential: {}", primary.credential_type);
    /// ```
    #[must_use]
    pub fn primary_credential(&self) -> Option<&VerifiedCredential> {
        self.credential_chain().last().copied()
    }

    /// Get the number of credentials in the response.
    #[must_use]
    pub const fn len(&self) -> usize {
        self.credentials.len()
    }

    /// Check if the response contains no credentials.
    #[must_use]
    pub const fn is_empty(&self) -> bool {
        self.credentials.is_empty()
    }

    // ============================================
    // Device & Verification Accessors (T050-T051)
    // ============================================

    /// Get device attestation data from the KB-JWT.
    ///
    /// Device attestation is shared across all credentials in the presentation.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// if let Some(attestation) = response.device_attestation() {
    ///     if attestation.is_high_security() {
    ///         println!("High security device");
    ///     }
    /// }
    /// ```
    #[must_use]
    pub const fn device_attestation(&self) -> Option<&DeviceAttestation> {
        self.device_attestation.as_ref()
    }

    /// Get device security context from the KB-JWT.
    ///
    /// Device security is shared across all credentials in the presentation.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// if let Some(security) = response.device_security() {
    ///     if security.is_high_security() && security.biometric_used {
    ///         println!("High security with biometric");
    ///     }
    /// }
    /// ```
    #[must_use]
    pub const fn device_security(&self) -> Option<&DeviceSecurity> {
        self.device_security.as_ref()
    }

    /// Get verification metadata for a specific field.
    ///
    /// # Arguments
    ///
    /// * `field_name` - The field to get verification for (e.g., "email")
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// if let Some(meta) = response.field_verification("email") {
    ///     if meta.verified {
    ///         println!("Email verified by: {:?}", meta.provider);
    ///     }
    /// }
    /// ```
    #[must_use]
    pub fn field_verification(&self, field_name: &str) -> Option<FieldVerificationMetadata> {
        self.field_verification
            .as_ref()
            .and_then(|v| v.get(field_name))
            .and_then(|v| serde_json::from_value(v.clone()).ok())
    }

    /// Check if all credentials in the response have verified signatures.
    #[must_use]
    pub fn all_signatures_verified(&self) -> bool {
        self.credentials.iter().all(|c| c.signature_verified)
    }

    /// Check if any credential in the response is expired.
    #[must_use]
    pub fn has_expired_credential(&self) -> bool {
        self.credentials.iter().any(VerifiedCredential::is_expired)
    }
}

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

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

    #[test]
    fn test_new_response() {
        let creds = vec![
            test_credential("LastID.Base"),
            test_credential("LastID.Persona"),
        ];

        let response = VerifiedResponse::new(creds);
        assert_eq!(response.len(), 2);
        assert!(!response.is_empty());
    }

    #[test]
    fn test_single_credential() {
        let response = VerifiedResponse::single(test_credential("LastID.Base"));
        assert_eq!(response.len(), 1);
    }

    #[test]
    fn test_credential_by_type() {
        let creds = vec![
            test_credential("LastID.Base"),
            test_credential("LastID.Persona"),
            test_credential("LastID.Employment"),
        ];

        let response = VerifiedResponse::new(creds);

        assert!(response.credential_by_type("LastID.Base").is_some());
        assert!(response.credential_by_type("LastID.Persona").is_some());
        assert!(response.credential_by_type("LastID.Employment").is_some());
        assert!(response.credential_by_type("LastID.Trust").is_none());
    }

    #[test]
    fn test_credential_chain() {
        let creds = vec![
            test_credential("LastID.Employment"),
            test_credential("LastID.Base"),
            test_credential("LastID.Persona"),
        ];

        let response = VerifiedResponse::new(creds);
        let chain: Vec<_> = response
            .credential_chain()
            .iter()
            .map(|c| c.credential_type.as_str())
            .collect();

        assert_eq!(
            chain,
            vec!["LastID.Base", "LastID.Persona", "LastID.Employment"]
        );
    }

    #[test]
    fn test_primary_credential() {
        let creds = vec![
            test_credential("LastID.Base"),
            test_credential("LastID.Employment"),
        ];

        let response = VerifiedResponse::new(creds);
        let primary = response.primary_credential().unwrap();
        assert_eq!(primary.credential_type, "LastID.Employment");
    }

    #[test]
    fn test_device_attestation() {
        let attestation = DeviceAttestation {
            has_secure_element: true,
            ..Default::default()
        };

        let response = VerifiedResponse::single(test_credential("LastID.Base"))
            .with_device_attestation(attestation);

        let att = response.device_attestation().unwrap();
        assert!(att.has_secure_element);
    }

    #[test]
    fn test_device_security() {
        let security = DeviceSecurity {
            security_level: "high".to_string(),
            biometric_used: true,
            platform: "ios".to_string(),
        };

        let response =
            VerifiedResponse::single(test_credential("LastID.Base")).with_device_security(security);

        let sec = response.device_security().unwrap();
        assert!(sec.is_high_security());
        assert!(sec.biometric_used);
    }

    #[test]
    fn test_field_verification() {
        let verification = serde_json::json!({
            "email": {
                "verified": true,
                "provider": "google",
                "method": "oauth"
            }
        });

        let response = VerifiedResponse::single(test_credential("LastID.Base"))
            .with_field_verification(verification);

        let meta = response.field_verification("email").unwrap();
        assert!(meta.verified);
        assert_eq!(meta.provider, Some("google".to_string()));
    }

    #[test]
    fn test_all_signatures_verified() {
        let creds = vec![
            test_credential("LastID.Base"),
            test_credential("LastID.Persona"),
        ];

        let response = VerifiedResponse::new(creds);
        assert!(response.all_signatures_verified());
    }

    #[test]
    fn test_has_expired_credential() {
        let mut expired = test_credential("LastID.Base");
        expired.expires_at = Utc::now() - chrono::Duration::hours(1);

        let creds = vec![expired, test_credential("LastID.Persona")];

        let response = VerifiedResponse::new(creds);
        assert!(response.has_expired_credential());
    }

    #[test]
    fn test_credentials_iterator() {
        let creds = vec![
            test_credential("LastID.Base"),
            test_credential("LastID.Persona"),
        ];

        let response = VerifiedResponse::new(creds);
        let types: Vec<_> = response
            .credentials()
            .map(|c| c.credential_type.as_str())
            .collect();

        assert_eq!(types.len(), 2);
        assert!(types.contains(&"LastID.Base"));
        assert!(types.contains(&"LastID.Persona"));
    }
}
