use anyhow::{bail, Result};
use tokio_retry::{
    strategy::{jitter, FibonacciBackoff},
    Retry,
};

use crate::utils::random_user_with_template;

const TMPL: &str = r#"
version = "0.1"
name = "Smoketest Template"

[inputs]
main = { type = "user", is-default = true, required = true, description = "The starting user" }

[objects]
main_space = { type = "space", is-default = true, name = "{{ main.display_name }}’s template test space" }
start_list = { type = "task-list", name = "{{ main.display_name }}’s Acter onboarding list" }

[objects.task_1]
type = "task"
title = "Scroll through the news"
assignees = ["{{ main.user_id }}"]
"m.relates_to" = { event_id = "{{ start_list.id }}" } 
utc_due = "{{ now().as_rfc3339 }}"

[objects.acter-website-pin]
type = "pin"
title = "Acter Website"
url = "https://acter.global"

[objects.acter-source-pin]
type = "pin"
title = "Acter Source Code"
url = "https://github.com/acterglobal/a3"

        "#;

#[tokio::test]
async fn template_creates_space() -> Result<()> {
    let _ = env_logger::try_init();
    let (user, sync_state, _engine) =
        random_user_with_template("template_create_space", TMPL).await?;
    sync_state.await_has_synced_history().await?;

    // wait for sync to catch up
    let retry_strategy = FibonacciBackoff::from_millis(100).map(jitter).take(10);
    Retry::spawn(retry_strategy, || async {
        if user.pins().await?.len() != 2 || user.task_lists().await?.len() != 1 {
            bail!("not all pins and task lists found");
        }
        Ok(())
    })
    .await?;

    assert_eq!(user.pins().await?.len(), 2);
    assert_eq!(user.task_lists().await?.len(), 1);

    let spaces = user.spaces().await?;
    assert_eq!(spaces.len(), 1);

    let main_space = spaces.first().expect("main space should be available");
    assert_eq!(main_space.pins().await?.len(), 2);
    assert_eq!(main_space.task_lists().await?.len(), 1);
    Ok(())
}
