package app.mealsmadeeasy.api.recipe.star;

import app.mealsmadeeasy.api.PostgresTestsExtension;
import app.mealsmadeeasy.api.recipe.Recipe;
import app.mealsmadeeasy.api.recipe.RecipeService;
import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserCreateException;
import app.mealsmadeeasy.api.user.UserService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Optional;
import java.util.UUID;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

@SpringBootTest
@ExtendWith(PostgresTestsExtension.class)
public class RecipeStarServiceTests {

    @Autowired
    private RecipeStarService recipeStarService;

    @Autowired
    private UserService userService;

    @Autowired
    private RecipeService recipeService;

    private User seedUser() {
        final String uuid = UUID.randomUUID().toString();
        try {
            return this.userService.createUser(uuid, uuid + "@test.com", "test");
        } catch (UserCreateException e) {
            throw new RuntimeException(e);
        }
    }

    private Recipe seedRecipe(User owner) {
        final RecipeCreateSpec spec = RecipeCreateSpec.builder()
                .slug(UUID.randomUUID().toString())
                .title("Test Recipe")
                .rawText("My great recipe has five ingredients.")
                .isPublic(true)
                .build();
        return this.recipeService.create(owner, spec, false);
    }

    @Test
    public void whenToggleCreates_findReturnsPresent() {
        final User user = this.seedUser();
        final Recipe recipe = this.seedRecipe(user);
        this.recipeStarService.toggle(recipe, user);
        assertThat(this.recipeStarService.find(recipe, user).isPresent(), is(true));
    }

    @Test
    public void whenToggleDeletes_findReturnsEmpty() {
        final User user = this.seedUser();
        final Recipe recipe = this.seedRecipe(user);
        this.recipeStarService.toggle(recipe, user); // create
        assertThat(this.recipeStarService.find(recipe, user).isPresent(), is(true));
        this.recipeStarService.toggle(recipe, user); // delete
        assertThat(this.recipeStarService.find(recipe, user).isEmpty(), is(true));
    }

    @Test
    public void whenNotStarred_toggleReturnsPresent() {
        final User user = this.seedUser();
        final Recipe recipe = this.seedRecipe(user);
        final Optional<RecipeStar> maybeRecipeStar = this.recipeStarService.toggle(recipe, user);
        assertThat(maybeRecipeStar.isPresent(), is(true));
    }

    @Test
    public void whenStarred_toggleReturnsEmpty() {
        final User user = this.seedUser();
        final Recipe recipe = this.seedRecipe(user);
        this.recipeStarService.toggle(recipe, user); // create
        assertThat(this.recipeStarService.find(recipe, user).isPresent(), is(true)); // check that it's there
        final Optional<RecipeStar> maybeRecipeStar = this.recipeStarService.toggle(recipe, user); // get rid
        assertThat(maybeRecipeStar.isEmpty(), is(true));
    }

}
