//! Vector / Hybrid lane — AVX-gated. Marked `#[ignore]` because Lance
//! crashes with `SIGILL` on hosts without AVX, and CI lanes that are
//! AVX-less should not run these. Local hosts run them via
//! `cargo test -p kb-app -- --ignored`.

mod common;

use common::TestEnv;

/// Panic if the host CPU lacks AVX. Mirrors the helper in
/// `kb-store-vector/tests/common/mod.rs` and `kb-search` so a
/// `--ignored` invocation on a non-AVX host fails loudly with a
/// clear message instead of crashing inside Lance's SIMD kernel.
fn require_avx_or_panic() {
    #[cfg(target_arch = "x86_64")]
    {
        assert!(
            std::is_x86_feature_detected!("avx"),
            "kb-app vector integration test requires AVX-capable hardware; \
             host CPU lacks AVX. Run on an AVX-capable machine."
        );
    }
}

// First run downloads ~470MB; expect ~30-60s warm, several minutes cold.
#[test]
#[ignore = "AVX-required (Lance SIMD kernels)"]
fn ingest_then_hybrid_search_returns_hits() {
    require_avx_or_panic();

    let env = TestEnv::with_embeddings();
    let report = kebab_app::ingest_with_config(env.config.clone(), env.scope(), true).unwrap();
    assert_eq!(report.errors, 0, "no per-file errors: {report:?}");
    assert_eq!(report.new, 3);

    let q = kebab_core::SearchQuery {
        text: "ownership".to_string(),
        mode: kebab_core::SearchMode::Hybrid,
        k: 10,
        filters: kebab_core::SearchFilters::default(),
    };
    let hits = kebab_app::search_with_config(env.config.clone(), q).unwrap();
    assert!(!hits.is_empty(), "expected hybrid hits for 'ownership'");
    let methods: Vec<_> = hits.iter().map(|h| h.retrieval.method).collect();
    assert!(
        methods.iter().all(|m| *m == kebab_core::SearchMode::Hybrid),
        "every hit must report method=Hybrid: {methods:?}"
    );
}

// First run downloads ~470MB; expect ~30-60s warm, several minutes cold.
#[test]
#[ignore = "AVX-required (Lance SIMD kernels)"]
fn ingest_then_vector_search_carries_embedding_model() {
    require_avx_or_panic();

    let env = TestEnv::with_embeddings();
    let report = kebab_app::ingest_with_config(env.config.clone(), env.scope(), true).unwrap();
    assert_eq!(report.errors, 0, "no per-file errors: {report:?}");
    assert_eq!(report.new, 3);

    let q = kebab_core::SearchQuery {
        text: "ownership".to_string(),
        mode: kebab_core::SearchMode::Vector,
        k: 10,
        filters: kebab_core::SearchFilters::default(),
    };
    let hits = kebab_app::search_with_config(env.config.clone(), q).unwrap();
    assert!(!hits.is_empty(), "expected vector hits for 'ownership'");

    // Vector mode dispatches through `VectorRetriever` and MUST stamp
    // each hit with the configured embedding_model id.
    let expected = kebab_core::EmbeddingModelId(env.config.models.embedding.model.clone());
    for h in &hits {
        assert_eq!(
            h.embedding_model,
            Some(expected.clone()),
            "vector-mode hit must carry embedding_model={expected:?}: {h:?}"
        );
        assert_eq!(
            h.retrieval.method,
            kebab_core::SearchMode::Vector,
            "vector-mode hit must report method=Vector"
        );
    }
}
