use std::fs; use std::path::Path; use std::process::Command; use chrono::{Days, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc}; use chrono_tz::Tz; use crate::config::Settings; use crate::error::StreamdError; use crate::models::RepositoryConfiguration; use crate::timesheet::load_repository_config; use super::load_markdown_shards; pub fn run(date: Option) -> Result<(), StreamdError> { let settings = Settings::load()?; let base_folder = Path::new(&settings.base_folder); let repo_config = load_repository_config(base_folder)?; let tz: Tz = repo_config .timezone .as_deref() .and_then(|s| s.parse().ok()) .unwrap_or(chrono_tz::UTC); let target_date: NaiveDate = match date { Some(s) => NaiveDate::parse_from_str(&s, "%Y%m%d").map_err(|_| { StreamdError::ConfigError("Invalid date format, expected YYYYMMDD".into()) })?, None => Utc::now().with_timezone(&tz).date_naive(), }; let day_start = tz .from_local_datetime(&NaiveDateTime::new(target_date, NaiveTime::MIN)) .earliest() .unwrap() .with_timezone(&Utc); let day_end = tz .from_local_datetime(&NaiveDateTime::new( target_date + Days::new(1), NaiveTime::MIN, )) .earliest() .unwrap() .with_timezone(&Utc); let all_shards = load_markdown_shards(base_folder, &RepositoryConfiguration::new(), tz)?; let mut daily_shards: Vec<_> = all_shards .into_iter() .filter(|s| { s.location .get("file_type") .map(|v| v == "daily") .unwrap_or(false) && s.moment >= day_start && s.moment < day_end }) .collect(); daily_shards.sort_by_key(|s| s.moment); let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); if let Some(shard) = daily_shards.first() { let file_path = shard.location.get("file").unwrap(); Command::new(&editor).arg(file_path).status()?; } else { let now_local = Utc::now().with_timezone(&tz); let file_name = now_local.format("%Y%m%d-%H%M%S_daily.md").to_string(); let file_path = base_folder.join(&file_name); fs::write(&file_path, "# ")?; Command::new(&editor).arg(&file_path).status()?; println!("Created {}", file_name); } Ok(()) }