package app.mealsmadeeasy.api.recipe.star;

import app.mealsmadeeasy.api.recipe.Recipe;
import app.mealsmadeeasy.api.recipe.RecipeRepository;
import app.mealsmadeeasy.api.recipe.RecipeService;
import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserRepository;
import app.mealsmadeeasy.api.util.NoSuchEntityWithIdException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class RecipeStarService {

    private final RecipeStarRepository recipeStarRepository;
    private final UserRepository userRepository;
    private final RecipeRepository  recipeRepository;
    private final RecipeService recipeService;

    @Deprecated
    public RecipeStar create(Recipe recipe, User owner) {
        final RecipeStar recipeStar = new RecipeStar();
        recipeStar.setOwner(owner);
        recipeStar.setRecipe(recipe);
        return this.recipeStarRepository.save(recipeStar);
    }

    @Deprecated
    public RecipeStar create(Integer recipeId, Integer ownerId) {
        return this.recipeStarRepository.findByRecipeIdAndOwnerId(recipeId, ownerId)
                .orElseGet(() -> {
                    final User owner = this.userRepository.findById((long) ownerId).orElseThrow(
                            () -> new NoSuchEntityWithIdException(User.class, ownerId)
                    );
                    final Recipe recipe = this.recipeRepository.findById(recipeId).orElseThrow(
                            () -> new NoSuchEntityWithIdException(Recipe.class, recipeId)
                    );
                    return this.create(recipe, owner);
                });
    }

    @Deprecated
    public RecipeStar create(String recipeOwnerUsername, String recipeSlug, User starer) {
        final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
        final Optional<RecipeStar> existing = this.recipeStarRepository.findByRecipeIdAndOwnerId(
                recipe.getId(),
                starer.getId()
        );
        return existing.orElseGet(() -> this.create(recipe, starer));
    }

    @PreAuthorize("@recipeSecurity.isViewableBy(#recipe, #starer)")
    public Optional<RecipeStar> toggle(Recipe recipe, User starer) {
        final Optional<RecipeStar> existing = this.find(recipe, starer);
        if (existing.isPresent()) {
            this.recipeStarRepository.delete(existing.get());
            return Optional.empty();
        } else {
            return Optional.of(this.create(recipe, starer));
        }
    }

    @PreAuthorize("@recipeSecurity.isViewableBy(#recipe, #starer)")
    public Optional<RecipeStar> find(Recipe recipe, User starer) {
        return this.recipeStarRepository.findByRecipeAndOwner(recipe, starer);
    }

    @Deprecated
    @PreAuthorize("@recipeSecurity.isViewableBy(#recipeOwnerUsername, #recipeSlug, #starer)")
    public Optional<RecipeStar> find(String recipeOwnerUsername, String recipeSlug, User starer) {
        final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
        return this.recipeStarRepository.findByRecipeIdAndOwnerId(recipe.getId(), starer.getId());
    }

    @Deprecated
    public void delete(Integer recipeId, Integer ownerId) {
        this.recipeStarRepository.deleteByRecipeIdAndOwnerId(recipeId, ownerId);
    }

    @Deprecated
    public void delete(String recipeOwnerUsername, String recipeSlug, User starer) {
        final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
        this.delete(recipe.getId(), starer.getId());
    }

}
