use jiff::Timestamp;
use secrecy::{ExposeSecret, SecretString};
use url::Url;
use super::FHIR_JSON;
use super::error::PixmError;
use super::identifier::SourceIdentifier;
use super::request::Request;
use ihe_atna::balp::{
Coded, DESTINATION_ROLE, Direction, Entity, EventKind, Exchange, Outcome, Peer, REST, SEARCH,
SOURCE_ROLE, request_text,
};
use ihe_atna::user::OnBehalfOf;
pub const ITI_83: Coded = Coded::fixed(
ihe_atna::balp::IHE_TRANSACTIONS,
"ITI-83",
"Mobile Patient Identifier Cross-reference Query",
);
#[must_use]
pub fn query_consumer() -> EventKind {
EventKind {
profile: "https://profiles.ihe.net/ITI/PIXm/StructureDefinition/IHE.PIXm.Query.Audit.Consumer",
event_type: REST,
subtypes: vec![ITI_83, SEARCH],
action: "E",
client: SOURCE_ROLE,
server: DESTINATION_ROLE,
}
}
pub(super) fn exchange<T>(
operation: &Url,
(request, source): (&Request, &SourceIdentifier),
on_behalf: &OnBehalfOf,
result: &Result<T, PixmError>,
) -> Exchange {
Exchange {
kind: query_consumer(),
recorded: Timestamp::now(),
outcome: outcome(result),
outcome_description: None,
direction: Direction::Sent {
server: Peer::server(&operation.join("..").unwrap_or_else(|_| operation.clone())),
},
on_behalf: on_behalf.clone(),
entities: vec![
Entity::Query(query(operation, request)),
Entity::Patient {
system: Some(source.system().to_owned()),
namespace: None,
value: source.value().clone(),
},
],
security: Vec::new(),
}
}
fn query(operation: &Url, request: &Request) -> SecretString {
match request {
Request::Get(url) => request_text(url),
Request::Post(body) => SecretString::from(format!(
"POST {}\nContent-Type: {FHIR_JSON}\n\n{}",
request_text(operation).expose_secret(),
body.expose_secret()
)),
}
}
fn outcome<T>(result: &Result<T, PixmError>) -> Outcome {
match result {
Ok(_) => Outcome::Success,
Err(PixmError::Timeout | PixmError::Transport(_)) => Outcome::SeriousFailure,
Err(_) => Outcome::MinorFailure,
}
}