use std::{collections::HashMap, env, fs, path::PathBuf};
use serde::Deserialize;
use crate::error::{AppResult, config_error};
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Config {
#[serde(default)]
pub llm: LlmConfig,
#[serde(default)]
pub retry: RetryConfig,
#[serde(default)]
pub rules: RulesConfig
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct RulesConfig {
#[serde(default)]
pub disabled: Vec<String>,
#[serde(default)]
pub severity: HashMap<String, String>
}
#[derive(Debug, Clone, Deserialize)]
pub struct LlmConfig {
pub provider: Option<String>,
pub api_key: Option<String>,
pub model: Option<String>,
pub ollama_url: Option<String>
}
impl Default for LlmConfig {
fn default() -> Self {
Self {
provider: None,
api_key: None,
model: None,
ollama_url: Some(String::from("http://localhost:11434"))
}
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct RetryConfig {
pub max_retries: u32,
pub initial_delay_ms: u64,
pub max_delay_ms: u64,
pub backoff_factor: f64
}
impl Default for RetryConfig {
fn default() -> Self {
Self {
max_retries: 3,
initial_delay_ms: 1000,
max_delay_ms: 30000,
backoff_factor: 2.0
}
}
}
impl Config {
pub fn load() -> AppResult<Self> {
let mut config = Self::default();
if let Some(home) = env::var_os("HOME") {
let home_config = PathBuf::from(home)
.join(".config")
.join("sql-analyzer")
.join("config.toml");
if home_config.exists() {
let content = fs::read_to_string(&home_config)
.map_err(|e| config_error(format!("Failed to read config file: {}", e)))?;
config = toml::from_str(&content)
.map_err(|e| config_error(format!("Invalid config file: {}", e)))?;
}
}
let local_config = PathBuf::from(".sql-analyzer.toml");
if local_config.exists() {
let content = fs::read_to_string(&local_config)
.map_err(|e| config_error(format!("Failed to read config file: {}", e)))?;
config = toml::from_str(&content)
.map_err(|e| config_error(format!("Invalid config file: {}", e)))?;
}
if let Ok(api_key) = env::var("LLM_API_KEY") {
config.llm.api_key = Some(api_key);
}
if let Ok(provider) = env::var("LLM_PROVIDER") {
config.llm.provider = Some(provider);
}
if let Ok(model) = env::var("LLM_MODEL") {
config.llm.model = Some(model);
}
if let Ok(url) = env::var("OLLAMA_URL") {
config.llm.ollama_url = Some(url);
}
Ok(config)
}
}