use crate::models::{Entry, EntryType};
pub fn process_entries(
entries: &[Entry],
query: Option<String>,
project: Option<String>,
entry_type: Option<EntryType>,
offset: Option<usize>,
limit: Option<usize>,
) -> Vec<&Entry> {
let normalized_query = query.map(|value| value.to_lowercase());
let mut entries: Vec<&Entry> = if let Some(query) = normalized_query.as_ref() {
let mut scored_entries: Vec<(&Entry, i32)> = entries
.iter()
.filter(|entry| {
project
.as_ref()
.is_none_or(|project| entry.project == *project)
})
.filter(|entry| {
entry_type
.as_ref()
.is_none_or(|entry_type| entry.entry_type == *entry_type)
})
.filter_map(|entry| {
let content_match = entry.content.to_lowercase().contains(query);
let project_match = entry.project.to_lowercase().contains(query);
let entry_type_match = entry.entry_type.as_str() == query;
let mut score = 0;
if content_match {
score += 3;
}
if project_match {
score += 2;
}
if entry_type_match {
score += 2;
}
(score > 0).then_some((entry, score))
})
.collect();
scored_entries.sort_by(|a, b| {
b.1.cmp(&a.1)
.then_with(|| b.0.timestamp.cmp(&a.0.timestamp))
});
scored_entries
.into_iter()
.map(|(entry, _score)| entry)
.collect()
} else {
entries
.iter()
.filter(|entry| {
project
.as_ref()
.is_none_or(|project| entry.project == *project)
})
.filter(|entry| {
entry_type
.as_ref()
.is_none_or(|entry_type| entry.entry_type == *entry_type)
})
.collect()
};
if normalized_query.is_none() {
entries.sort_by(|a, b| b.timestamp.cmp(&a.timestamp));
}
if let Some(offset) = offset {
entries = entries.into_iter().skip(offset).collect();
}
if let Some(limit) = limit {
return entries.into_iter().take(limit).collect();
}
entries
}