//! Basic query engine tests: empty store, subject filter, lifecycle filter, limit, all filters.

use std::sync::Arc;
use stemedb_core::types::LifecycleStage;
use stemedb_storage::HybridStore;

use super::{create_test_assertion, store_assertion, QueryEngine};
use crate::query::Query;

#[tokio::test]
async fn test_query_empty_store() {
    let store = Arc::new(HybridStore::open_temp().expect("store"));
    let engine = QueryEngine::new(Arc::new(store));

    let query = Query::builder().subject("Tesla").build();
    let result = engine.execute(&query).await.expect("execute");

    assert!(result.assertions.is_empty());
    assert_eq!(result.total_count, 0);
}

#[tokio::test]
async fn test_query_by_subject() {
    let store = Arc::new(HybridStore::open_temp().expect("store"));

    let tesla = create_test_assertion("Tesla", "revenue", LifecycleStage::Approved);
    let apple = create_test_assertion("Apple", "revenue", LifecycleStage::Approved);

    store_assertion(&store, &tesla).await;
    store_assertion(&store, &apple).await;

    let engine = QueryEngine::new(Arc::new(store));

    let query = Query::builder().subject("Tesla").build();
    let result = engine.execute(&query).await.expect("execute");

    assert_eq!(result.assertions.len(), 1);
    assert_eq!(result.assertions[0].subject, "Tesla");
}

#[tokio::test]
async fn test_query_by_lifecycle() {
    let store = Arc::new(HybridStore::open_temp().expect("store"));

    let approved = create_test_assertion("Tesla", "revenue", LifecycleStage::Approved);
    let proposed = create_test_assertion("Tesla", "profit", LifecycleStage::Proposed);

    store_assertion(&store, &approved).await;
    store_assertion(&store, &proposed).await;

    let engine = QueryEngine::new(Arc::new(store));

    // Query only approved
    let query = Query::builder().subject("Tesla").lifecycle(LifecycleStage::Approved).build();
    let result = engine.execute(&query).await.expect("execute");

    assert_eq!(result.assertions.len(), 1);
    assert_eq!(result.assertions[0].lifecycle, LifecycleStage::Approved);
}

#[tokio::test]
async fn test_query_with_limit() {
    let store = Arc::new(HybridStore::open_temp().expect("store"));

    // Store multiple assertions
    for i in 0..5 {
        let assertion =
            create_test_assertion(&format!("Entity_{}", i), "property", LifecycleStage::Approved);
        store_assertion(&store, &assertion).await;
    }

    let engine = QueryEngine::new(Arc::new(store));

    let query = Query::builder().limit(2).build();
    let result = engine.execute(&query).await.expect("execute");

    assert_eq!(result.assertions.len(), 2);
    assert_eq!(result.total_count, 5);
    assert!(result.has_more);
}

#[tokio::test]
async fn test_query_all_filters() {
    let store = Arc::new(HybridStore::open_temp().expect("store"));

    let target = create_test_assertion("Tesla", "revenue", LifecycleStage::Approved);
    let wrong_subject = create_test_assertion("Apple", "revenue", LifecycleStage::Approved);
    let wrong_predicate = create_test_assertion("Tesla", "profit", LifecycleStage::Approved);
    let wrong_lifecycle = create_test_assertion("Tesla", "revenue", LifecycleStage::Proposed);

    store_assertion(&store, &target).await;
    store_assertion(&store, &wrong_subject).await;
    store_assertion(&store, &wrong_predicate).await;
    store_assertion(&store, &wrong_lifecycle).await;

    let engine = QueryEngine::new(Arc::new(store));

    let query = Query::builder()
        .subject("Tesla")
        .predicate("revenue")
        .lifecycle(LifecycleStage::Approved)
        .build();

    let result = engine.execute(&query).await.expect("execute");

    assert_eq!(result.assertions.len(), 1);
    assert_eq!(result.assertions[0].subject, "Tesla");
    assert_eq!(result.assertions[0].predicate, "revenue");
    assert_eq!(result.assertions[0].lifecycle, LifecycleStage::Approved);
}
