use std::path::Path;

use anyhow::Result;

use astmap_core::port::FileDiscovery;
use astmap_core::scanner::scan as core_scan;
use astmap_core::{LanguageRegistry, ScanResult, ScanStore};

pub fn scan(
    project_dir: &Path,
    full: bool,
    db: &dyn ScanStore,
    lang: &dyn LanguageRegistry,
    discovery: &dyn FileDiscovery,
) -> Result<ScanResult> {
    let result = core_scan(project_dir, db, full, lang, discovery)?;
    Ok(result)
}

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

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

        let db = crate::infra::sqlite::open(dir.path()).unwrap();
        let result = scan(
            dir.path(),
            false,
            db.as_ref(),
            &DefaultLanguageRegistry,
            &IgnoreWalkDiscovery,
        )
        .unwrap();
        assert!(result.symbols > 0);
    }

    #[test]
    fn full_scan_reparses_all() {
        let dir = tempfile::tempdir().unwrap();
        let src = dir.path().join("src");
        fs::create_dir_all(&src).unwrap();
        fs::write(src.join("main.rs"), "fn main() {}\nfn helper() {}").unwrap();

        let db = crate::infra::sqlite::open(dir.path()).unwrap();
        let r1 = scan(
            dir.path(),
            false,
            db.as_ref(),
            &DefaultLanguageRegistry,
            &IgnoreWalkDiscovery,
        )
        .unwrap();
        let r2 = scan(
            dir.path(),
            true,
            db.as_ref(),
            &DefaultLanguageRegistry,
            &IgnoreWalkDiscovery,
        )
        .unwrap();
        assert_eq!(r1.symbols, r2.symbols);
    }

    #[test]
    fn scan_empty_project() {
        let dir = tempfile::tempdir().unwrap();
        let src = dir.path().join("src");
        fs::create_dir_all(&src).unwrap();

        let db = crate::infra::sqlite::open(dir.path()).unwrap();
        let result = scan(
            dir.path(),
            false,
            db.as_ref(),
            &DefaultLanguageRegistry,
            &IgnoreWalkDiscovery,
        )
        .unwrap();
        assert_eq!(result.symbols, 0);
    }
}
