use anyhow::Result;

use astmap_core::model::SymbolResult;
use astmap_core::QueryStore;

use super::query_symbols;

pub fn query(db: &dyn QueryStore, pattern: &str, limit: i64) -> Result<Vec<SymbolResult>> {
    let results = query_symbols(db, pattern, limit)?;
    Ok(results)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::infra::discovery::IgnoreWalkDiscovery;
    use astmap_languages::DefaultLanguageRegistry;
    use std::fs;

    fn setup_db(dir: &std::path::Path) -> Box<dyn QueryStore> {
        let db = crate::infra::sqlite::open(dir).unwrap();
        astmap_core::scanner::scan(
            dir,
            db.as_ref(),
            false,
            &DefaultLanguageRegistry,
            &IgnoreWalkDiscovery,
        )
        .unwrap();
        db
    }

    #[test]
    fn finds_symbol_by_name() {
        let dir = tempfile::tempdir().unwrap();
        let src = dir.path().join("src");
        fs::create_dir_all(&src).unwrap();
        fs::write(src.join("lib.rs"), "pub fn hello() {}").unwrap();

        let db = setup_db(dir.path());
        let results = query(db.as_ref(), "hello", 10).unwrap();
        assert_eq!(results.len(), 1);
        assert_eq!(results[0].name, "hello");
    }

    #[test]
    fn empty_db_returns_empty() {
        let dir = tempfile::tempdir().unwrap();
        let db = crate::infra::sqlite::open(dir.path()).unwrap();
        let results = query(db.as_ref(), "anything", 10).unwrap();
        assert!(results.is_empty());
    }

    #[test]
    fn respects_limit() {
        let dir = tempfile::tempdir().unwrap();
        let src = dir.path().join("src");
        fs::create_dir_all(&src).unwrap();
        fs::write(
            src.join("lib.rs"),
            "pub fn aaa() {}\npub fn aab() {}\npub fn aac() {}",
        )
        .unwrap();

        let db = setup_db(dir.path());
        let results = query(db.as_ref(), "aa", 2).unwrap();
        assert!(results.len() <= 2);
    }
}
