use anyhow::Result;

use astmap_core::model::Config;
use astmap_core::ConfigStore;

pub fn config_get(db: &dyn ConfigStore, key: &str) -> Result<Option<String>> {
    let val = db.config_get(key)?;
    Ok(val)
}

pub fn config_set(db: &dyn ConfigStore, key: &str, value: &str) -> Result<()> {
    db.config_set(key, value)?;
    Ok(())
}

pub fn config_list(db: &dyn ConfigStore) -> Result<Vec<Config>> {
    let configs = db.config_list()?;
    Ok(configs)
}

#[cfg(test)]
mod tests {
    use super::*;

    fn setup_db(dir: &std::path::Path) -> Box<dyn ConfigStore> {
        crate::infra::sqlite::open(dir).unwrap()
    }

    #[test]
    fn set_and_get() {
        let dir = tempfile::tempdir().unwrap();
        let db = setup_db(dir.path());
        config_set(db.as_ref(), "test.key", "val").unwrap();
        let val = config_get(db.as_ref(), "test.key").unwrap();
        assert_eq!(val, Some("val".to_string()));
    }

    #[test]
    fn get_missing_key() {
        let dir = tempfile::tempdir().unwrap();
        let db = setup_db(dir.path());
        let val = config_get(db.as_ref(), "no.such.key").unwrap();
        assert_eq!(val, None);
    }

    #[test]
    fn set_overwrites() {
        let dir = tempfile::tempdir().unwrap();
        let db = setup_db(dir.path());
        config_set(db.as_ref(), "k", "v1").unwrap();
        config_set(db.as_ref(), "k", "v2").unwrap();
        let val = config_get(db.as_ref(), "k").unwrap();
        assert_eq!(val, Some("v2".to_string()));
    }

    #[test]
    fn list_returns_all() {
        let dir = tempfile::tempdir().unwrap();
        let db = setup_db(dir.path());
        config_set(db.as_ref(), "a", "1").unwrap();
        config_set(db.as_ref(), "b", "2").unwrap();
        let list = config_list(db.as_ref()).unwrap();
        assert!(list.len() >= 2);
        let keys: Vec<_> = list.iter().map(|c| c.key.as_str()).collect();
        assert!(keys.contains(&"a"));
        assert!(keys.contains(&"b"));
    }

    #[test]
    fn list_empty_db() {
        let dir = tempfile::tempdir().unwrap();
        let db = setup_db(dir.path());
        let list = config_list(db.as_ref()).unwrap();
        assert!(list.is_empty());
    }
}
