use chromiumoxide::element::Element;
use chrono::NaiveDate;
use crate::error::Result;
use super::super::client::{
SENATE_BASE, SenateTradesClient, find_element_if_present, wait_for_element, wait_for_elements,
};
use super::super::models::SenateFilingEntry;
const PAGE_LENGTH: &str = "100";
pub(super) fn parse_us_date(raw: &str) -> Option<NaiveDate> {
NaiveDate::parse_from_str(raw.trim(), "%m/%d/%Y").ok()
}
pub(super) async fn search_recent_ptrs(
client: &SenateTradesClient,
) -> Result<Vec<SenateFilingEntry>> {
let page = client
.new_page(&format!("{SENATE_BASE}/search/home/"))
.await?;
if let Some(checkbox) = find_element_if_present(&page, "#agree_statement").await {
checkbox.click().await.ok();
}
wait_for_element(&page, "#filerTypeLabelSenator")
.await?
.click()
.await
.ok();
wait_for_element(&page, "#reportTypeLabelPtr")
.await?
.click()
.await
.ok();
wait_for_element(&page, "#searchForm button[type=submit]")
.await?
.click()
.await
.ok();
wait_for_elements(&page, "#filedReports tbody tr").await?;
page.evaluate(format!(
"$('#filedReports').DataTable().page.len({PAGE_LENGTH}).draw();"
))
.await
.ok();
let rows = wait_for_elements(&page, "#filedReports tbody tr").await?;
let mut entries = Vec::with_capacity(rows.len());
for row in &rows {
if let Some(entry) = parse_row(row).await {
entries.push(entry);
}
}
entries.sort_by_key(|e| std::cmp::Reverse(parse_us_date(&e.filed_date)));
Ok(entries)
}
async fn parse_row(row: &Element) -> Option<SenateFilingEntry> {
let cells = row.find_elements("td").await.ok()?;
let first_name = cells.first()?.inner_text().await.ok()??;
let last_name = cells.get(1)?.inner_text().await.ok()??;
let filed_date = cells.get(4)?.inner_text().await.ok()??;
let link = cells.get(3)?.find_element("a").await.ok()?;
let path = link.attribute("href").await.ok()??;
Some(SenateFilingEntry {
first_name: first_name.trim().to_string(),
last_name: last_name.trim().to_string(),
filed_date: filed_date.trim().to_string(),
path,
})
}