use super::CURRENT_CONFIG_VERSION;
use anyhow::{Context, Result};
use std::fs;
use std::path::Path;
pub fn check_and_upgrade_config(config_path: &Path) -> Result<bool> {
let config_content =
fs::read_to_string(config_path).context("Failed to read config file for version check")?;
let parsed_toml: toml::Value =
toml::from_str(&config_content).context("Failed to parse config file for version check")?;
let current_version = parsed_toml
.get("version")
.and_then(|v| v.as_integer())
.unwrap_or(0) as u32;
if current_version < CURRENT_CONFIG_VERSION {
println!(
"🔄 Config version {current_version} detected, upgrading to version {CURRENT_CONFIG_VERSION}..."
);
let upgraded_content = migrate_config_content(&config_content, current_version)?;
let backup_path = config_path.with_extension("toml.backup");
fs::copy(config_path, &backup_path).context("Failed to create config backup")?;
fs::write(config_path, upgraded_content).context("Failed to write upgraded config")?;
println!(
"✅ Config upgraded successfully! Backup saved to: {}",
backup_path.display()
);
return Ok(true);
}
Ok(false)
}
fn migrate_config_content(content: &str, from_version: u32) -> Result<String> {
let mut lines: Vec<String> = content.lines().map(|s| s.to_string()).collect();
let mut current_version = from_version;
while current_version < CURRENT_CONFIG_VERSION {
match current_version {
0 => {
let mut version_found = false;
for line in lines.iter_mut() {
if line.trim().starts_with("version = ") {
*line = "version = 1".to_string();
version_found = true;
break;
}
}
if !version_found {
let mut insert_pos = 0;
for (i, line) in lines.iter().enumerate() {
let trimmed = line.trim();
if !trimmed.is_empty() && !trimmed.starts_with('#') {
insert_pos = i;
break;
}
}
lines.insert(
insert_pos,
"# Configuration version (DO NOT MODIFY - used for automatic upgrades)"
.to_string(),
);
lines.insert(insert_pos + 1, "version = 1".to_string());
lines.insert(insert_pos + 2, "".to_string());
}
current_version = 1;
}
_ => {
current_version += 1;
}
}
}
println!("🔄 Applied migration from version {from_version} to {current_version}");
Ok(lines.join("\n"))
}
pub fn force_upgrade_config(config_path: &Path) -> Result<()> {
if !config_path.exists() {
return Err(anyhow::anyhow!(
"Config file not found: {}",
config_path.display()
));
}
let config_content = fs::read_to_string(config_path).context("Failed to read config file")?;
let parsed_toml: toml::Value =
toml::from_str(&config_content).context("Failed to parse config file")?;
let current_version = parsed_toml
.get("version")
.and_then(|v| v.as_integer())
.unwrap_or(0) as u32;
if current_version >= CURRENT_CONFIG_VERSION {
println!("✅ Config is already at the latest version ({current_version})");
return Ok(());
}
println!("🔄 Upgrading config from version {current_version} to {CURRENT_CONFIG_VERSION}...");
let upgraded_content = migrate_config_content(&config_content, current_version)?;
let backup_path = config_path.with_extension("toml.backup");
fs::copy(config_path, &backup_path).context("Failed to create config backup")?;
fs::write(config_path, upgraded_content).context("Failed to write upgraded config")?;
println!(
"✅ Config upgraded successfully! Backup saved to: {}",
backup_path.display()
);
Ok(())
}