use db::{Db, catalog};
use domain::{AuditActor, ObjectInput, Visibility};
use search::SearchClient;
use sqlx::PgPool;

fn meili() -> (String, String) {
    (
        std::env::var("MEILI_URL").expect("MEILI_URL must be set"),
        std::env::var("MEILI_MASTER_KEY").expect("MEILI_MASTER_KEY must be set"),
    )
}

fn unique_index() -> String {
    format!("sync_test_{}", uuid::Uuid::new_v4().simple())
}

fn object(number: &str, name: &str) -> ObjectInput {
    ObjectInput {
        object_number: number.into(),
        object_name: name.into(),
        number_of_objects: 1,
        brief_description: None,
        current_location: None,
        current_owner: None,
        recorder: None,
        recording_date: None,
        visibility: Visibility::Draft,
    }
}

#[sqlx::test(migrations = "../db/migrations")]
async fn sync_object_indexes_then_removes(pool: PgPool) {
    let db = Db::from_pool(pool);

    let mut tx = db.pool().begin().await.unwrap();

    let id = catalog::create_object(&mut tx, AuditActor::System, &object("S-1", "lamp"))
        .await
        .unwrap();

    tx.commit().await.unwrap();

    let (url, key) = meili();
    let client = SearchClient::connect(&url, &key, &unique_index()).unwrap();

    client.ensure_index().await.unwrap();

    // object exists -> sync indexes it
    client.sync_object(&db, id).await.unwrap();
    assert_eq!(client.search("lamp").await.unwrap(), vec![id]);

    // object deleted -> sync removes it from the index
    let mut tx = db.pool().begin().await.unwrap();

    let existed = catalog::delete_object(&mut tx, AuditActor::System, id)
        .await
        .unwrap();
    assert!(existed);

    tx.commit().await.unwrap();

    client.sync_object(&db, id).await.unwrap();
    assert!(client.search("lamp").await.unwrap().is_empty());
}
