use crate::{
    Database, Filter, Query, Value,
    test_shared::{AGE, NAME, new_alice, new_bob, new_charlie},
};
use anyhow::Result;
use jellyobject::Path;

#[test]
pub fn insert_get() -> Result<()> {
    let db = jellykv::memory::new();

    let mut bob_row = 0;
    db.transaction(&mut |txn| {
        bob_row = txn.insert(new_bob())?;
        Ok(())
    })?;

    let mut bob = None;
    db.transaction(&mut |txn| {
        bob = txn.get(bob_row)?;
        Ok(())
    })?;

    assert_eq!(bob.unwrap().get(NAME).unwrap(), "Bob");
    Ok(())
}

#[test]
pub fn update() -> Result<()> {
    let db = jellykv::memory::new();

    let mut bob_row = 0;
    let mut bob = None;

    db.transaction(&mut |txn| {
        bob_row = txn.insert(new_bob())?;
        Ok(())
    })?;
    db.transaction(&mut |txn| {
        let better_bob = new_bob().insert(NAME, "Better Bob");
        txn.update(bob_row, better_bob)?;
        Ok(())
    })?;
    db.transaction(&mut |txn| {
        bob = txn.get(bob_row)?;
        Ok(())
    })?;

    assert_eq!(bob.unwrap().get(NAME).unwrap(), "Better Bob");
    Ok(())
}

#[test]
pub fn query_match_int() -> Result<()> {
    let db = jellykv::memory::new();

    let mut rows = [0, 0, 0];
    let mut result = None;

    db.transaction(&mut |txn| {
        rows = [
            txn.insert(new_bob())?,
            txn.insert(new_alice())?,
            txn.insert(new_charlie())?,
        ];
        Ok(())
    })?;
    db.transaction(&mut |txn| {
        result = txn.query_single(Query {
            filter: Filter::Match(Path(vec![AGE.0]), Value::U32(35)),
            ..Default::default()
        })?;
        Ok(())
    })?;

    assert_eq!(result, Some(rows[0]));
    Ok(())
}

#[test]
pub fn query_match_str() -> Result<()> {
    let db = jellykv::memory::new();

    let mut rows = [0, 0, 0];
    let mut result = None;

    db.transaction(&mut |txn| {
        rows = [
            txn.insert(new_bob())?,
            txn.insert(new_alice())?,
            txn.insert(new_charlie())?,
        ];
        Ok(())
    })?;
    db.transaction(&mut |txn| {
        result = txn.query_single(Query {
            filter: Filter::Match(Path(vec![NAME.0]), "Alice".into()),
            ..Default::default()
        })?;
        Ok(())
    })?;

    assert_eq!(result, Some(rows[1]));
    Ok(())
}

#[test]
pub fn query_match_str_after() -> Result<()> {
    let db = jellykv::memory::new();

    let mut rows = [0, 0, 0];
    let mut result = None;

    db.transaction(&mut |txn| {
        result = txn.query_single(Query {
            filter: Filter::Match(Path(vec![NAME.0]), "Alice".into()),
            ..Default::default()
        })?;
        Ok(())
    })?;
    assert_eq!(result, None);

    db.transaction(&mut |txn| {
        rows = [
            txn.insert(new_bob())?,
            txn.insert(new_alice())?,
            txn.insert(new_charlie())?,
        ];
        Ok(())
    })?;

    db.transaction(&mut |txn| {
        result = txn.query_single(Query {
            filter: Filter::Match(Path(vec![NAME.0]), "Alice".into()),
            ..Default::default()
        })?;
        Ok(())
    })?;
    assert_eq!(result, Some(rows[1]));

    Ok(())
}
