use chrono::{Local, NaiveDate};
use tracing::info;
use crate::error::Result;
use crate::scraper::{CalendarParser, HttpCalendarFetcher};
use crate::types::{EconomicEvent, EventQuery, Impact};
pub struct CalendarService {
fetcher: HttpCalendarFetcher,
parser: CalendarParser,
}
impl CalendarService {
pub fn new() -> Result<Self> {
let fetcher = HttpCalendarFetcher::new()?;
let parser = CalendarParser::new()?;
Ok(Self { fetcher, parser })
}
pub fn with_timezone(timezone: &str) -> Result<Self> {
let fetcher = HttpCalendarFetcher::with_timezone(timezone)?;
let parser = CalendarParser::new()?;
Ok(Self { fetcher, parser })
}
pub async fn query_events(&self, query: &EventQuery) -> Result<Vec<EconomicEvent>> {
let base_date = query.from_date.unwrap_or_else(|| Local::now().date_naive());
info!("Fetching calendar for date: {base_date}");
let html = self.fetcher.fetch_date(base_date).await?;
let events = self.parser.parse(&html, base_date);
let min_impact = query.min_impact.unwrap_or(Impact::Low);
let filtered: Vec<EconomicEvent> = events
.into_iter()
.filter(|e| e.meets_impact(min_impact))
.filter(|e| e.matches_currencies(&query.currencies))
.filter(|e| query.datetime_in_range(&e.datetime))
.collect();
info!("Found {} events matching query", filtered.len());
Ok(filtered)
}
pub async fn get_today_events(&self) -> Result<Vec<EconomicEvent>> {
let today = Local::now().date_naive();
let html = self.fetcher.fetch_today().await?;
Ok(self.parser.parse(&html, today))
}
pub async fn get_week_events(&self) -> Result<Vec<EconomicEvent>> {
let today = Local::now().date_naive();
let html = self.fetcher.fetch_this_week().await?;
Ok(self.parser.parse(&html, today))
}
pub async fn get_week_events_for(&self, date: NaiveDate) -> Result<Vec<EconomicEvent>> {
let html = self.fetcher.fetch_date(date).await?;
Ok(self.parser.parse(&html, date))
}
}