#![cfg(feature = "redis")]

use async_std::sync::{Arc, Mutex};
use common::*;
use std::time::Duration;

mod common;

#[tokio::test]
async fn integration_basic() {
    let invocations = Arc::new(Mutex::new(Vec::default()));
    let job_server = create_server(invocations.clone()).await;
    job_server
        .enqueue(TestCommand {
            name: "basic".to_string(),
            outcome: Outcome::Success,
        })
        .await
        .expect("Enqueue job");

    assert_invocations(1, "basic", invocations.clone()).await;
}

#[tokio::test]
async fn integration_retry() {
    let invocations = Arc::new(Mutex::new(Vec::default()));
    let job_server = create_server(invocations.clone()).await;
    job_server
        .enqueue(TestCommand {
            name: "retry".to_string(),
            outcome: Outcome::Retry(3),
        })
        .await
        .expect("Enqueue job");

    assert_invocations(3, "retry", invocations.clone()).await;
}

#[tokio::test]
async fn integration_delayed() {
    let invocations = Arc::new(Mutex::new(Vec::default()));
    let job_server = create_server(invocations.clone()).await;
    job_server
        .enqueue_delayed(
            TestCommand {
                name: "delay".to_string(),
                outcome: Outcome::Delay(500),
            },
            Duration::from_secs(5),
        )
        .await
        .expect("Enqueue job");

    assert_invocations_with_delay(
        1,
        Some(Duration::from_secs(5)),
        "delay",
        invocations.clone(),
    )
    .await;
}

#[tokio::test]
async fn integration_continuation_basic() {
    let invocations = Arc::new(Mutex::new(Vec::default()));
    let job_server = create_server(invocations.clone()).await;
    let parent_job_id = job_server
        .enqueue(TestCommand {
            name: "continuation-1".to_string(),
            outcome: Outcome::Delay(100),
        })
        .await
        .expect("Enqueue job");

    let child_job_1 = job_server
        .enqueue_continue(
            parent_job_id,
            TestCommand {
                name: "continuation-2".to_string(),
                outcome: Outcome::Retry(3),
            },
        )
        .await
        .expect("Enqueue job");

    let _ = job_server
        .enqueue_continue(
            child_job_1,
            TestCommand {
                name: "continuation-3".to_string(),
                outcome: Outcome::Success,
            },
        )
        .await
        .expect("Enqueue job");

    println!("--- All job scheduled ---");

    assert_invocations(1, "continuation-3", invocations.clone()).await;
    assert_invocations(3, "continuation-2", invocations.clone()).await;
    assert_invocations(1, "continuation-1", invocations.clone()).await;
}

#[tokio::test]
async fn integration_continuation_multiple() {
    let invocations = Arc::new(Mutex::new(Vec::default()));
    let job_server = create_server(invocations.clone()).await;
    let parent_job_id = job_server
        .enqueue(TestCommand {
            name: "continuation-multiple-1".to_string(),
            outcome: Outcome::Delay(250),
        })
        .await
        .expect("Enqueue job");

    let _ = job_server
        .enqueue_continue(
            parent_job_id.clone(),
            TestCommand {
                name: "continuation-multiple-2".to_string(),
                outcome: Outcome::Retry(3),
            },
        )
        .await
        .expect("Enqueue job");

    let _ = job_server
        .enqueue_continue(
            parent_job_id,
            TestCommand {
                name: "continuation-multiple-3".to_string(),
                outcome: Outcome::Success,
            },
        )
        .await
        .expect("Enqueue job");

    println!("--- All job scheduled ---");

    assert_invocations(3, "continuation-multiple-2", invocations.clone()).await;
    assert_invocations(1, "continuation-multiple-3", invocations.clone()).await;
    assert_invocations(1, "continuation-multiple-1", invocations.clone()).await;
}
