use crate::error::Result;
use std::env;

pub struct EnvironmentConfiguration {
  pub rust_log: String,
  pub discord_token: String,
  pub discord_secret: String,
  pub jwt_secret: String,
  pub postgres_user: String,
  pub postgres_password: String,
  pub postgres_database: String,
  pub postgres_host: String,
  pub postgres_port: u16,
  pub api_base_url: String,
  pub api_port: u16,
  pub api_session_ttl: u64,
  pub valkey_host: String,
  pub valkey_port: u16,
  pub data_dir_path: Option<String>,
  pub force_command_register: bool,
}

impl EnvironmentConfiguration {
  pub fn load() -> Result<Self> {
    Ok(Self {
      rust_log: env::var("RUST_LOG").unwrap_or_else(|_| "warn,siren=info".to_string()),
      discord_token: env::var("DISCORD_BOT_TOKEN")?,
      discord_secret: env::var("DISCORD_CLIENT_SECRET")?,
      jwt_secret: env::var("JWT_SECRET")?,
      postgres_user: env::var("POSTGRES_USER")?,
      postgres_password: env::var("POSTGRES_PASSWORD")?,
      postgres_database: env::var("POSTGRES_DB")?,
      postgres_host: env::var("POSTGRES_HOST")?,
      postgres_port: env::var("POSTGRES_PORT")
        .unwrap_or_else(|_| "5432".to_string())
        .parse()
        .unwrap_or(5432),
      api_base_url: env::var("API_BASE_URL")?,
      api_port: env::var("API_PORT")
        .unwrap_or_else(|_| "3000".to_string())
        .parse()
        .unwrap_or(3000),
      api_session_ttl: env::var("API_SESSION_TTL")
        .unwrap_or_else(|_| "86400".to_string())
        .parse()
        .unwrap_or(86400),
      valkey_host: env::var("VALKEY_HOST").unwrap_or_else(|_| "localhost".to_string()),
      valkey_port: env::var("VALKEY_PORT")
        .unwrap_or_else(|_| "6379".to_string())
        .parse()
        .unwrap_or(6379),
      data_dir_path: env::var("DATA_DIR_PATH").ok().filter(|s| !s.is_empty()),
      force_command_register: env::var("FORCE_COMMAND_REGISTER")
        .ok()
        .map(|v| v.to_lowercase() == "true")
        .unwrap_or(false),
    })
  }
}
