use std::collections::BTreeSet;
use chrono::{DateTime, FixedOffset};
use serde::{Deserialize, Serialize};
use crate::item::{address::Address, flag::Flag};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ItemSummary {
pub id: String,
#[serde(default)]
pub message_id: Option<String>,
#[serde(default)]
pub in_reply_to: Vec<String>,
#[serde(default)]
pub flags: BTreeSet<Flag>,
#[serde(default)]
pub subject: String,
#[serde(default)]
pub from: Vec<Address>,
#[serde(default)]
pub to: Vec<Address>,
#[serde(default)]
pub cc: Vec<Address>,
#[serde(default)]
pub bcc: Vec<Address>,
#[serde(default)]
pub date: Option<DateTime<FixedOffset>>,
#[serde(default)]
pub size: u64,
#[serde(default)]
pub has_attachment: Option<bool>,
}
#[cfg_attr(not(any(feature = "imap", feature = "msgraph")), allow(dead_code))]
pub fn parse_message_ids(raw: &str) -> Vec<String> {
if raw.contains('<') {
return raw
.split('<')
.filter_map(|rest| rest.split_once('>'))
.filter_map(|(id, _)| normalize_message_id(id))
.collect();
}
raw.split_whitespace()
.filter_map(normalize_message_id)
.collect()
}
#[cfg_attr(not(any(feature = "imap", feature = "msgraph")), allow(dead_code))]
pub fn normalize_message_id(raw: &str) -> Option<String> {
let trimmed = raw.trim();
let inner = trimmed
.strip_prefix('<')
.and_then(|s| s.strip_suffix('>'))
.unwrap_or(trimmed)
.trim();
if inner.is_empty() {
None
} else {
Some(inner.to_string())
}
}