mod common;
use std::ops::Not;

#[test]
fn test_sync_subscription_getters() -> anyhow::Result<()> {
    let ditto = common::get_inactive_builder_ditto(None)?;
    test_sync_subscription_getters_impl(ditto)?;

    let ditto = common::get_inactive_revamp_ditto(None)?;
    test_sync_subscription_getters_impl(ditto)?;

    Ok(())
}

fn test_sync_subscription_getters_impl(
    ditto: dittolive_ditto::prelude::Ditto,
) -> anyhow::Result<()> {
    let sync_subscription = ditto.sync().register_subscription_v2((
        "SELECT * FROM cars WHERE color=:color",
        serde_json::json!({ "color": "red" }),
    ))?;

    assert_eq!(
        sync_subscription.query_string(),
        "SELECT * FROM cars WHERE color=:color"
    );

    let args = sync_subscription.query_arguments().unwrap();
    let args_json = serde_json::to_value(&args)?;
    assert_eq!(args_json, serde_json::json!({ "color": "red" }));

    assert!(sync_subscription.is_cancelled().not());
    sync_subscription.cancel();
    assert!(sync_subscription.is_cancelled());

    Ok(())
}

#[test]
fn test_sync_subscription_getters_args_none() -> anyhow::Result<()> {
    let ditto = common::get_inactive_builder_ditto(None)?;
    test_sync_subscription_getters_args_none_impl(ditto)?;

    let ditto = common::get_inactive_revamp_ditto(None)?;
    test_sync_subscription_getters_args_none_impl(ditto)?;

    Ok(())
}

fn test_sync_subscription_getters_args_none_impl(
    ditto: dittolive_ditto::prelude::Ditto,
) -> anyhow::Result<()> {
    let sync_subscription = ditto
        .sync()
        .register_subscription_v2("SELECT * FROM cars")?;

    assert_eq!(sync_subscription.query_string(), "SELECT * FROM cars");
    let maybe_args = sync_subscription.query_arguments();
    assert!(maybe_args.is_none());

    assert!(sync_subscription.is_cancelled().not());
    sync_subscription.cancel();
    assert!(sync_subscription.is_cancelled());

    Ok(())
}

// Creating identical subscriptions should still yield individual handles
#[test]
fn test_sync_subscription_unique_handles() -> anyhow::Result<()> {
    let ditto = common::get_inactive_builder_ditto(None)?;
    test_sync_subscription_unique_handles_impl(ditto)?;

    let ditto = common::get_inactive_revamp_ditto(None)?;
    test_sync_subscription_unique_handles_impl(ditto)?;

    Ok(())
}

fn test_sync_subscription_unique_handles_impl(
    ditto: dittolive_ditto::prelude::Ditto,
) -> anyhow::Result<()> {
    let sync1 = ditto.sync().register_subscription_v2((
        "SELECT * FROM cars WHERE color=:color",
        serde_json::json!({"color": "red"}),
    ))?;
    assert_eq!(ditto.sync().subscriptions_v2().len(), 1);

    let sync2 = ditto.sync().register_subscription_v2((
        "SELECT * FROM cars WHERE color=:color",
        serde_json::json!({"color": "red"}),
    ))?;
    assert_eq!(ditto.sync().subscriptions_v2().len(), 2);

    sync1.cancel();
    assert_eq!(ditto.sync().subscriptions_v2().len(), 1);

    sync2.cancel();
    assert_eq!(ditto.sync().subscriptions_v2().len(), 0);

    Ok(())
}
