use lb_rs::io::network::ApiError;
use lb_rs::model::api::*;
use lb_rs::model::file_metadata::FileDiff;
use test_utils::*;
use uuid::Uuid;

#[tokio::test]
async fn delete_document() {
    let core = test_core_with_account().await;
    let account = core.get_account().unwrap();
    let doc = core.create_at_path("test.md").await.unwrap().id;
    core.sync().await.unwrap();

    let doc1 = local(&core)
        .begin_tx()
        .await
        .db()
        .base_metadata
        .get()
        .get(&doc)
        .unwrap()
        .clone();
    let mut doc2 = doc1.clone();
    doc2.timestamped_value.value.set_deleted(true);
    local(&core)
        .client
        .request(&account, UpsertRequestV2 { updates: vec![FileDiff::edit(doc1, doc2)] })
        .await
        .unwrap();
}

#[tokio::test]
async fn delete_document_not_found() {
    let core = test_core_with_account().await;
    let account = core.get_account().unwrap();
    let doc = core.create_at_path("test.md").await.unwrap().id;
    core.sync().await.unwrap();
    let mut doc1 = local(&core)
        .begin_tx()
        .await
        .db()
        .base_metadata
        .get()
        .get(&doc)
        .unwrap()
        .clone();
    doc1.timestamped_value.value.set_id(Uuid::new_v4());

    // delete document
    let mut doc2 = doc1.clone();
    doc2.timestamped_value.value.set_deleted(true);
    let result = local(&core)
        .client
        .request(
            &account,
            UpsertRequestV2 {
                // create document as if deleting an existing document
                updates: vec![FileDiff::edit(doc1, doc2)],
            },
        )
        .await;
    assert_matches!(result, Err(ApiError::<UpsertError>::Endpoint(UpsertError::OldFileNotFound)));
}

#[tokio::test]
async fn delete_document_new_document() {
    let core = test_core_with_account().await;
    let account = core.get_account().unwrap();

    let doc = core.create_at_path("test.md").await.unwrap().id;
    let mut doc = local(&core)
        .begin_tx()
        .await
        .db()
        .local_metadata
        .get()
        .get(&doc)
        .unwrap()
        .clone();
    doc.timestamped_value.value.set_deleted(true);

    let result = local(&core)
        .client
        .request(&account, UpsertRequestV2 { updates: vec![FileDiff::new(doc)] })
        .await;
    assert_matches!(result, Ok(_));
}

#[tokio::test]
async fn delete_document_deleted() {
    let core = test_core_with_account().await;
    let account = core.get_account().unwrap();

    let doc = core.create_at_path("test.md").await.unwrap().id;
    let doc = local(&core)
        .begin_tx()
        .await
        .db()
        .local_metadata
        .get()
        .get(&doc)
        .unwrap()
        .clone();
    core.sync().await.unwrap();

    // delete document
    let mut doc2 = doc.clone();
    doc2.timestamped_value.value.set_deleted(true);
    local(&core)
        .client
        .request(&account, UpsertRequestV2 { updates: vec![FileDiff::edit(doc, doc2)] })
        .await
        .unwrap();
}

#[tokio::test]
async fn delete_cannot_delete_root() {
    let core = test_core_with_account().await;
    let account = core.get_account().unwrap();
    let root = core.root().await.unwrap().id;
    let root1 = local(&core)
        .begin_tx()
        .await
        .db()
        .base_metadata
        .get()
        .get(&root)
        .unwrap()
        .clone();

    let mut root2 = root1.clone();
    root2.timestamped_value.value.set_deleted(true);
    let result = local(&core)
        .client
        .request(&account, UpsertRequestV2 { updates: vec![FileDiff::edit(root1, root2)] })
        .await;
    assert_matches!(
        result,
        Err(ApiError::<UpsertError>::Endpoint(UpsertError::RootModificationInvalid))
    );
}
