use anyhow::Result;
use std::path::PathBuf;
use crate::config::Config;
use crate::storage::history;
pub fn export_to_csv() -> Result<PathBuf> {
let history = history::load_history()?;
let exports_dir = Config::config_dir()?.join("exports");
std::fs::create_dir_all(&exports_dir)?;
let filename = format!(
"speedtest_{}.csv",
chrono::Local::now().format("%Y-%m-%d_%H-%M-%S")
);
let path = exports_dir.join(&filename);
let mut writer = csv::Writer::from_path(&path)?;
writer.write_record([
"timestamp",
"provider",
"server",
"ping_ms",
"jitter_ms",
"download_mbps",
"download_peak_mbps",
"upload_mbps",
"upload_peak_mbps",
"ip",
"isp",
"location",
])?;
for entry in &history {
writer.write_record([
entry.timestamp.format("%Y-%m-%d %H:%M:%S").to_string(),
entry.provider.clone(),
entry.server.clone().unwrap_or_default(),
entry
.ping
.as_ref()
.map(|p| format!("{:.2}", p.latency_ms))
.unwrap_or_default(),
entry
.ping
.as_ref()
.map(|p| format!("{:.2}", p.jitter_ms))
.unwrap_or_default(),
entry
.download
.as_ref()
.map(|d| format!("{:.2}", d.speed_mbps))
.unwrap_or_default(),
entry
.download
.as_ref()
.map(|d| format!("{:.2}", d.peak_speed_mbps))
.unwrap_or_default(),
entry
.upload
.as_ref()
.map(|u| format!("{:.2}", u.speed_mbps))
.unwrap_or_default(),
entry
.upload
.as_ref()
.map(|u| format!("{:.2}", u.peak_speed_mbps))
.unwrap_or_default(),
entry
.connection_info
.as_ref()
.map(|c| c.ip.clone())
.unwrap_or_default(),
entry
.connection_info
.as_ref()
.and_then(|c| c.isp.clone())
.unwrap_or_default(),
entry
.connection_info
.as_ref()
.and_then(|c| c.location.clone())
.unwrap_or_default(),
])?;
}
writer.flush()?;
Ok(path)
}
#[allow(dead_code)]
pub fn export_result_to_json(
result: &crate::network::SpeedTestResult,
path: &PathBuf,
) -> Result<()> {
let content = serde_json::to_string_pretty(result)?;
std::fs::write(path, content)?;
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn test_export_empty_history() {
}
}