#![allow(deprecated)] // TODO(v5): remove entire test module

use_prelude!();
use serde_json::json;

use super::*;
use crate::{
    prelude::DocumentId,
    store::collection::document::{DittoDocument as _, DittoMutDocument as _},
    test_helpers::setup_ditto,
    utils::prelude::ErrorKind,
};

#[test]
fn create_in_document() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();
    let doc_id = DocumentId::new(&"test_register").unwrap();
    let doc = collection.find_by_id(doc_id).exec();
    assert!(doc.is_err());
    let e = doc.err().unwrap();
    let error_kind = e.kind();
    assert_eq!(error_kind, ErrorKind::NonExtant);
    let content = json!({"_id": "test_register" ,"register": DittoRegister::new(12.12).unwrap()});
    let doc_id = collection.upsert(content).unwrap();
    let doc = collection.find_by_id(doc_id).exec();
    assert!(doc.is_ok());
}

#[test]
fn init() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();
    let doc_id = collection.upsert(json!({})).unwrap();
    collection
        .find_by_id(&doc_id)
        .update(|mut_doc| {
            let mut_doc = mut_doc.unwrap();

            let register = DittoRegister::new(42.0f64).unwrap();
            mut_doc.set("register", register).unwrap();
        })
        .unwrap();

    let doc = collection.find_by_id(doc_id).exec().unwrap();

    let register: DittoRegister = doc.get("register").unwrap();
    assert_eq!(register.value::<f64>().unwrap(), 42.0);
}

#[test]
fn overwrite() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();

    let doc_id = collection.upsert(json!({})).unwrap();
    collection
        .find_by_id(doc_id)
        .update(|mut_doc| {
            let mut_doc = mut_doc.unwrap();

            let register = DittoRegister::new(42.0f64).unwrap();
            mut_doc.set("register", register).unwrap();
        })
        .unwrap();

    let payload = String::from("Terre brûlée au vent");

    let doc_id = collection.upsert(json!({})).unwrap();
    collection
        .find_by_id(&doc_id)
        .update(|mut_doc| {
            let mut_doc = mut_doc.unwrap();

            let register = DittoRegister::new(payload.clone()).unwrap();
            mut_doc.set("register", register).unwrap();
        })
        .unwrap();

    let doc = collection.find_by_id(&doc_id).exec().unwrap();
    let register: DittoRegister = doc.get("register").unwrap();
    assert_eq!(register.value::<String>().unwrap(), payload);
}

#[test]
fn set_content() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();

    let doc_id = collection
        .upsert(json!({"register": DittoRegister::new(42u64).unwrap()}))
        .unwrap();
    collection
        .find_by_id(&doc_id)
        .update(|mut_doc| {
            let mut_doc = mut_doc.unwrap();
            let _register: DittoRegister = mut_doc.get("register").unwrap();
            let mut register: DittoMutableRegister<'_> = mut_doc.get_mut("register").unwrap();
            register.set(std::f64::consts::PI).unwrap();
        })
        .unwrap();

    let doc = collection.find_by_id(&doc_id).exec().unwrap();
    let register: DittoRegister = doc.get("register").unwrap();
    assert_eq!(register.value::<f64>().unwrap(), std::f64::consts::PI);
}

#[test]
fn primitive_to_register() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();

    let text = String::from("🤖♫-bip▓b0op♥");
    let integer = 42u16;
    let float = std::f64::consts::PI;
    let doc_id = collection
        .upsert(json!({"string": text, "integer": integer, "float":float}))
        .unwrap();

    let doc = collection.find_by_id(doc_id).exec().unwrap();

    let register: DittoRegister = doc.get("string").unwrap();
    assert_eq!(register.value::<String>().unwrap(), text);
    let register: DittoRegister = doc.get("integer").unwrap();
    assert_eq!(register.value::<u16>().unwrap(), integer);
    let register: DittoRegister = doc.get("float").unwrap();
    assert_eq!(register.value::<f64>().unwrap(), float);
}
#[test]
fn multiple_set_content() {
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();

    let doc_id = collection
        .upsert(json!({"register": DittoRegister::new(42u64).unwrap()}))
        .unwrap();
    collection
        .find_by_id(&doc_id)
        .update(|mut_doc| {
            let mut_doc = mut_doc.unwrap();
            let _register: DittoRegister = mut_doc.get("register").unwrap();
            let mut register: DittoMutableRegister<'_> = mut_doc.get_mut("register").unwrap();
            register.set(i64::MAX).unwrap();
            register.set(std::f64::consts::PI).unwrap();
        })
        .unwrap();

    let doc = collection.find_by_id(&doc_id).exec().unwrap();
    let register: DittoRegister = doc.get("register").unwrap();
    assert_eq!(register.value::<f64>().unwrap(), std::f64::consts::PI);
}

#[test]
fn set_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
    struct Data {
        index: u32,
        text: String,
    }
    let ditto = setup_ditto().unwrap();
    let store = ditto.store();
    let collection = store.collection("test").unwrap();
    let data = Data {
        index: 22,
        text: String::from("Un druide est giboyeux quand il se prend pour un neutrino"),
    };

    let doc_id = collection
        .upsert(json!({"register": DittoRegister::new(data.clone()).unwrap()}))
        .unwrap();

    let doc = collection.find_by_id(doc_id).exec().unwrap();
    let register: DittoRegister = doc.get("register").unwrap();
    assert_eq!(data, register.value().unwrap());
}
