use auths_core::storage::keychain::KeyAlias;
use auths_id::keri::Event;
use auths_id::keri::types::Prefix;
use auths_keri::witness::StoredReceipt;
use auths_keri::{Said, TelEvent};
use crate::context::AuthsContext;
use crate::domains::credentials::error::CredentialError;
use crate::domains::credentials::stored::StoredCredential;
use crate::domains::credentials::verify::{
ResolvedAsOf, collect_lifecycle_receipts, resolve_kel, resolve_tel, tip_as_of,
};
#[derive(Debug, Clone)]
pub struct PresentationInputs {
pub signed: auths_verifier::SignedAcdc,
pub issuer_kel: Vec<Event>,
pub tel: Vec<TelEvent>,
pub receipts: Vec<StoredReceipt>,
pub subject_kel: Vec<Event>,
pub subject_delegator_kel: Vec<Event>,
pub as_of: ResolvedAsOf,
}
pub fn load_presentation_inputs(
ctx: &AuthsContext,
issuer_alias: &KeyAlias,
credential_said: &str,
) -> Result<PresentationInputs, CredentialError> {
let issuer_prefix =
crate::domains::credentials::issue::resolve_issuer_prefix(ctx, issuer_alias)?;
let cred = Said::new_unchecked(credential_said.to_string());
let blob = ctx
.registry
.load_credential(&issuer_prefix, &cred)
.map_err(|e| CredentialError::StaleOrUnresolvable {
reason: format!("credential blob read failed: {e}"),
})?
.ok_or_else(|| CredentialError::StaleOrUnresolvable {
reason: format!("credential not found: {credential_said}"),
})?;
let stored =
StoredCredential::from_bytes(&blob).map_err(|e| CredentialError::StaleOrUnresolvable {
reason: format!("credential blob parse failed: {e}"),
})?;
let issuer_kel = resolve_kel(ctx, &issuer_prefix)?;
let tel = resolve_tel(ctx, &issuer_prefix, &stored.acdc.ri, &stored.acdc.d)?;
let receipts = collect_lifecycle_receipts(ctx, &issuer_prefix, &issuer_kel, &tel);
let as_of = tip_as_of(&issuer_kel);
let subject_prefix = Prefix::new_unchecked(stored.acdc.a.i.to_string());
let subject_kel = resolve_kel(ctx, &subject_prefix)?;
let subject_delegator_kel = match subject_delegator_prefix(&subject_kel) {
Some(delegator) => resolve_kel(ctx, &delegator)?,
None => Vec::new(),
};
let signed = auths_verifier::SignedAcdc {
acdc: stored.acdc.clone(),
signature: stored.signature.clone(),
};
Ok(PresentationInputs {
signed,
issuer_kel,
tel,
receipts,
subject_kel,
subject_delegator_kel,
as_of,
})
}
fn subject_delegator_prefix(subject_kel: &[Event]) -> Option<Prefix> {
subject_kel
.iter()
.find_map(|event| event.delegator().cloned())
}