use luci_index::index::Index;
use luci_mapping::{FieldType,Mapping};
use serde_json::json;

fn main() {
    // 1. Define a schema
    let schema = Mapping::builder()
        .field("title", FieldType::Text)
        .field("body", FieldType::Text)
        .field("tag", FieldType::Keyword)
        .build();

    // 2. Create an index
    let path = std::env::temp_dir().join("luci_quickstart");
    let _ = std::fs::remove_dir_all(&path);

    let mut index = Index::create_with_mapping(&path, schema).expect("failed to create index");

    // 3. Add documents
    let docs = vec![
        json!({"title": "The Rust Programming Language", "body": "Rust is a systems programming language focused on safety and performance.", "tag": "programming"}),
        json!({"title": "Search Engine Design", "body": "Building a search engine requires inverted indexes, scoring algorithms, and query parsing.", "tag": "search"}),
        json!({"title": "Database Internals", "body": "Understanding storage engines, B-trees, and write-ahead logs.", "tag": "databases"}),
        json!({"title": "Information Retrieval", "body": "The science of searching for information in documents, including BM25 scoring and relevance ranking.", "tag": "search"}),
        json!({"title": "Systems Programming in Rust", "body": "Using Rust to build high-performance systems like databases and search engines.", "tag": "programming"}),
    ];

    for doc in docs {
        index.add(doc).expect("failed to add document");
    }
    index.commit().expect("failed to commit");

    println!("Indexed 5 documents.\n");

    // 4. Search — term query on keyword field
    println!("=== Term query: tag = \"search\" ===");
    let results = index
        .search(json!({"term": {"tag": "search"}}), 10)
        .expect("search failed");
    println!("Hits: {}", results.total_hits.value);
    for hit in &results.hits {
        let src = hit.source.as_ref().unwrap();
        println!("  [{:.3}] {}", hit.score, src["title"]);
    }

    // 5. Search — full-text match query
    println!("\n=== Match query: body = \"search engine\" ===");
    let results = index
        .search(json!({"match": {"body": "search engine"}}), 10)
        .expect("search failed");
    println!("Hits: {}", results.total_hits.value);
    for hit in &results.hits {
        let src = hit.source.as_ref().unwrap();
        println!("  [{:.3}] {}", hit.score, src["title"]);
    }

    // 6. Search — phrase query
    println!("\n=== Phrase query: body = \"search engine\" ===");
    let results = index
        .search(json!({"match_phrase": {"body": "search engine"}}), 10)
        .expect("search failed");
    println!("Hits: {}", results.total_hits.value);
    for hit in &results.hits {
        let src = hit.source.as_ref().unwrap();
        println!("  [{:.3}] {}", hit.score, src["title"]);
    }

    // 7. Search — bool query: must match "rust" AND tag = "programming"
    println!("\n=== Bool query: match \"rust\" AND tag = \"programming\" ===");
    let results = index
        .search(
            json!({
                "bool": {
                    "must": [{"match": {"body": "rust"}}],
                    "filter": [{"term": {"tag": "programming"}}]
                }
            }),
            10,
        )
        .expect("search failed");
    println!("Hits: {}", results.total_hits.value);
    for hit in &results.hits {
        let src = hit.source.as_ref().unwrap();
        println!("  [{:.3}] {}", hit.score, src["title"]);
    }

    // 8. Search — match_all
    println!("\n=== Match all ===");
    let results = index
        .search(json!({"match_all": {}}), 10)
        .expect("search failed");
    println!("Hits: {}", results.total_hits.value);

    // Cleanup
    let _ = std::fs::remove_dir_all(&path);
    println!("\nDone.");
}
