use regex::Regex;
use std::path::PathBuf;
use tracing::debug;
pub fn rotate_file_if_needed(
file_path: &PathBuf,
max_size: u64,
) -> Result<Option<PathBuf>, std::io::Error> {
if !file_path.exists() {
return Ok(None);
}
let metadata = std::fs::metadata(file_path)?;
if metadata.len() <= max_size {
return Ok(None);
}
let timestamp = chrono::Utc::now().format("%Y%m%d_%H%M%S");
let parent = file_path
.parent()
.unwrap_or_else(|| std::path::Path::new("."));
let stem = file_path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("file");
let extension = file_path.extension().and_then(|s| s.to_str()).unwrap_or("");
let timestamp_pattern = Regex::new(r"_\d{8}_\d{6}$").unwrap();
let base_stem = if timestamp_pattern.is_match(stem) {
timestamp_pattern.replace(stem, "").to_string()
} else {
stem.to_string()
};
let new_filename = format!("{}_{}.{}", base_stem, timestamp, extension);
let new_path = if new_filename.len() > 250 {
let seq_pattern = Regex::new(r"_(\d+)$").unwrap();
let next_num = if let Some(captures) = seq_pattern.captures(&base_stem) {
captures
.get(1)
.and_then(|m| m.as_str().parse::<usize>().ok())
.map(|n| n + 1)
.unwrap_or(1)
} else {
1
};
let clean_base = seq_pattern.replace(&base_stem, "").to_string();
parent.join(format!("{}_{}.{}", clean_base, next_num, extension))
} else {
parent.join(new_filename)
};
debug!(
"Rotating file {} ({} bytes) to {}",
file_path.display(),
metadata.len(),
new_path.display()
);
Ok(Some(new_path))
}