use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::types::{
BirthDate, JobId, PassportData, PhoneNumber, Pinfl, Reuid, SessionId, Threshold,
};
#[derive(Debug, Serialize)]
pub struct SessionWithPinfl {
pinfl: Pinfl,
birth_date: BirthDate,
#[serde(flatten)]
options: SessionOptions,
}
impl SessionWithPinfl {
pub fn new(pinfl: Pinfl, birth_date: BirthDate) -> Self {
Self {
pinfl,
birth_date,
options: SessionOptions::default(),
}
}
#[must_use]
pub fn with_phone_number(mut self, phone_number: PhoneNumber) -> Self {
self.options.phone_number = Some(phone_number);
self
}
#[must_use]
pub fn with_is_resident(mut self, is_resident: bool) -> Self {
self.options.is_resident = Some(is_resident);
self
}
#[must_use]
pub fn with_threshold(mut self, threshold: Threshold) -> Self {
self.options.threshold = Some(threshold);
self
}
pub fn pinfl(&self) -> &Pinfl {
&self.pinfl
}
pub fn birth_date(&self) -> BirthDate {
self.birth_date
}
pub fn phone_number(&self) -> Option<&PhoneNumber> {
self.options.phone_number.as_ref()
}
pub fn is_resident(&self) -> Option<bool> {
self.options.is_resident
}
pub fn threshold(&self) -> Option<Threshold> {
self.options.threshold
}
}
#[derive(Debug, Serialize)]
pub struct SessionWithPassport {
pass_data: PassportData,
birth_date: BirthDate,
#[serde(flatten)]
options: SessionOptions,
}
impl SessionWithPassport {
pub fn new(pass_data: PassportData, birth_date: BirthDate) -> Self {
Self {
pass_data,
birth_date,
options: SessionOptions::default(),
}
}
#[must_use]
pub fn with_phone_number(mut self, phone_number: PhoneNumber) -> Self {
self.options.phone_number = Some(phone_number);
self
}
#[must_use]
pub fn with_is_resident(mut self, is_resident: bool) -> Self {
self.options.is_resident = Some(is_resident);
self
}
#[must_use]
pub fn with_threshold(mut self, threshold: Threshold) -> Self {
self.options.threshold = Some(threshold);
self
}
pub fn pass_data(&self) -> &PassportData {
&self.pass_data
}
pub fn birth_date(&self) -> BirthDate {
self.birth_date
}
pub fn phone_number(&self) -> Option<&PhoneNumber> {
self.options.phone_number.as_ref()
}
pub fn is_resident(&self) -> Option<bool> {
self.options.is_resident
}
pub fn threshold(&self) -> Option<Threshold> {
self.options.threshold
}
}
#[derive(Debug, Serialize)]
pub struct SessionWithReuid {
reuid: Reuid,
#[serde(skip_serializing_if = "Option::is_none")]
phone_number: Option<PhoneNumber>,
}
impl SessionWithReuid {
pub fn new(reuid: Reuid) -> Self {
Self {
reuid,
phone_number: None,
}
}
#[must_use]
pub fn with_phone_number(mut self, phone_number: PhoneNumber) -> Self {
self.phone_number = Some(phone_number);
self
}
pub fn reuid(&self) -> Reuid {
self.reuid
}
pub fn phone_number(&self) -> Option<&PhoneNumber> {
self.phone_number.as_ref()
}
}
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum CreateSessionRequest {
WithPinfl(SessionWithPinfl),
WithPassport(SessionWithPassport),
WithReuid(SessionWithReuid),
Empty {},
}
#[derive(Debug, Deserialize)]
pub struct SessionResponse {
session_id: SessionId,
}
impl SessionResponse {
pub fn session_id(&self) -> SessionId {
self.session_id
}
}
#[derive(Debug, Deserialize)]
pub struct SessionStatusResponse {
code: Option<String>,
status: SessionStatus,
attempts: Vec<SessionAttempt>,
}
impl SessionStatusResponse {
pub fn code(&self) -> Option<&str> {
self.code.as_deref()
}
pub fn status(&self) -> &SessionStatus {
&self.status
}
pub fn attempts(&self) -> &[SessionAttempt] {
&self.attempts
}
}
#[derive(Debug, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SessionStatus {
#[serde(alias = "IN_PROGRESS")]
InProgress,
#[serde(alias = "CLOSED")]
Closed,
#[serde(alias = "EXPIRED")]
Expired,
}
impl SessionStatus {
pub fn is_in_progress(&self) -> bool {
matches!(self, Self::InProgress)
}
pub fn is_closed(&self) -> bool {
matches!(self, Self::Closed)
}
pub fn is_expired(&self) -> bool {
matches!(self, Self::Expired)
}
}
#[derive(Debug, Deserialize)]
pub struct SessionAttempt {
job_id: JobId,
timestamp: DateTime<Utc>,
reason: Option<String>,
reason_code: Option<i32>,
}
impl SessionAttempt {
pub fn job_id(&self) -> JobId {
self.job_id
}
pub fn timestamp(&self) -> &DateTime<Utc> {
&self.timestamp
}
pub fn reason(&self) -> Option<&str> {
self.reason.as_deref()
}
pub fn reason_code(&self) -> Option<i32> {
self.reason_code
}
}
#[derive(Debug, Default, Serialize)]
struct SessionOptions {
#[serde(skip_serializing_if = "Option::is_none")]
phone_number: Option<PhoneNumber>,
#[serde(skip_serializing_if = "Option::is_none")]
is_resident: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
threshold: Option<Threshold>,
}