use chrono::{DateTime, Utc};
use proptest::prelude::*;
use turnframe_core::case::{CaseKey, CaseRef};
use turnframe_core::hash::Digest;
use turnframe_core::ids::{
AccountId, AttachmentId, CaseId, CaseRevision, CommandId, ConversationId, EventId,
InteractionId, OperationKey, OptionId, OriginToken, ReceiptId, TargetToken, TurnId, UserId,
WorkflowKey,
};
use turnframe_core::locale::Locale;
use uuid::Uuid;
pub const LABEL_WORDS: [&str; 8] = [
"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
];
pub const LOCALES: [&str; 4] = ["en", "en-GB", "it", "it-IT"];
pub fn uuid() -> impl Strategy<Value = Uuid> {
any::<[u8; 16]>().prop_map(Uuid::from_bytes)
}
pub fn label() -> impl Strategy<Value = String> {
(proptest::sample::select(&LABEL_WORDS[..]), 0_u8..8)
.prop_map(|(word, index)| format!("{word}-{index}"))
}
pub fn account_id() -> impl Strategy<Value = AccountId> {
label().prop_map(AccountId::new)
}
pub fn user_id() -> impl Strategy<Value = UserId> {
label().prop_map(UserId::new)
}
pub fn case_id() -> impl Strategy<Value = CaseId> {
label().prop_map(CaseId::new)
}
pub fn workflow_key() -> impl Strategy<Value = WorkflowKey> {
proptest::sample::select(&["trip", "traveler", "note"][..]).prop_map(WorkflowKey::from)
}
pub fn operation_key() -> impl Strategy<Value = OperationKey> {
(workflow_key(), label()).prop_map(|(workflow, name)| {
OperationKey::new(format!("{workflow}.{}", name.replace('-', "_")))
})
}
pub fn option_id() -> impl Strategy<Value = OptionId> {
label().prop_map(OptionId::new)
}
pub fn target_token() -> impl Strategy<Value = TargetToken> {
label().prop_map(|value| TargetToken::new(format!("t_{value}")))
}
pub fn origin_token() -> impl Strategy<Value = OriginToken> {
label().prop_map(|value| OriginToken::new(format!("o_{value}")))
}
pub fn attachment_id() -> impl Strategy<Value = AttachmentId> {
label().prop_map(|value| AttachmentId::new(format!("att_{value}")))
}
pub fn conversation_id() -> impl Strategy<Value = ConversationId> {
uuid().prop_map(ConversationId::from)
}
pub fn turn_id() -> impl Strategy<Value = TurnId> {
uuid().prop_map(TurnId::from)
}
pub fn interaction_id() -> impl Strategy<Value = InteractionId> {
uuid().prop_map(InteractionId::from)
}
pub fn command_id() -> impl Strategy<Value = CommandId> {
uuid().prop_map(CommandId::from)
}
pub fn event_id() -> impl Strategy<Value = EventId> {
uuid().prop_map(EventId::from)
}
pub fn receipt_id() -> impl Strategy<Value = ReceiptId> {
uuid().prop_map(ReceiptId::from)
}
pub fn case_revision() -> impl Strategy<Value = CaseRevision> {
(0_u64..64).prop_map(CaseRevision)
}
pub fn digest() -> impl Strategy<Value = Digest> {
any::<[u8; 16]>().prop_map(|bytes| Digest::of_bytes(&bytes))
}
pub fn case_key() -> impl Strategy<Value = CaseKey> {
(workflow_key(), case_id()).prop_map(|(workflow, case_id)| CaseKey { workflow, case_id })
}
pub fn case_ref() -> impl Strategy<Value = CaseRef> {
(case_key(), case_revision()).prop_map(|(key, revision)| key.at(revision))
}
pub fn locale() -> impl Strategy<Value = Locale> {
proptest::sample::select(&LOCALES[..]).prop_map(Locale::from)
}
pub fn instant() -> impl Strategy<Value = DateTime<Utc>> {
(1_000_000_000_i64..2_000_000_000_i64).prop_filter_map("timestamp out of range", |seconds| {
DateTime::from_timestamp(seconds, 0)
})
}