use crate::domain::embedding::Embedder;
use crate::infrastructure::embeddings::dummy_provider::DummyEmbedding;
use std::fmt;
use std::path::Path;
use std::sync::Arc;
use tracing::debug;
use crate::config::{load_settings, Settings};
pub struct Context {
pub embedder: Arc<dyn Embedder>,
}
impl fmt::Debug for Context {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Context")
.field("embedder", &"Arc<dyn Embedder>")
.finish()
}
}
impl Context {
pub fn new(embedder: Arc<dyn Embedder>) -> Self {
Self { embedder }
}
}
#[derive(Debug)]
pub struct AppState {
pub context: Context,
pub settings: Settings,
}
impl Default for AppState {
fn default() -> Self {
Self::new(Arc::new(DummyEmbedding))
}
}
impl AppState {
pub fn new(embedder: Arc<dyn Embedder>) -> Self {
Self::new_with_config_file(embedder, None)
}
pub fn new_with_config_file(embedder: Arc<dyn Embedder>, config_file: Option<&Path>) -> Self {
let settings = load_settings(config_file).unwrap_or_else(|e| {
debug!("Failed to load settings: {}. Using defaults.", e);
Settings::default()
});
Self {
context: Context::new(embedder),
settings,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::util::testing::{init_test_env, EnvGuard};
use std::env;
#[test]
fn given_no_environment_when_new_then_defaults() {
let _ = init_test_env();
let _guard = EnvGuard::new();
env::remove_var("BKMR_DB_URL");
env::remove_var("BKMR_FZF_OPTS");
let state = AppState::default();
assert!(state.settings.db_url.contains("bkmr.db"));
assert_eq!(state.settings.fzf_opts.height, "50%");
assert!(!state.settings.fzf_opts.reverse);
assert!(!state.settings.fzf_opts.show_tags);
}
#[test]
fn given_env_vars_when_new_then_overrides() {
let _ = init_test_env();
let _guard = EnvGuard::new();
env::set_var("BKMR_DB_URL", "/test/db.db");
env::set_var("BKMR_FZF_OPTS", "--height 99% --reverse --show-tags");
let state = AppState::default();
assert_eq!(state.settings.db_url, "/test/db.db");
assert_eq!(state.settings.fzf_opts.height, "99%");
assert!(state.settings.fzf_opts.reverse);
assert!(state.settings.fzf_opts.show_tags);
}
}