package com.wishurgift.service.bean;

import com.wishurgift.persistence.entity.Shared;
import com.wishurgift.persistence.entity.User;
import com.wishurgift.persistence.entity.Wishlist;
import com.wishurgift.persistence.repository.SharedRepository;
import com.wishurgift.persistence.repository.UserRepository;
import com.wishurgift.persistence.repository.WishlistRepository;
import com.wishurgift.service.ElementService;
import com.wishurgift.service.WishlistService;
import com.wishurgift.service.dto.*;
import com.wishurgift.service.dto.request.ElementRequestDTO;
import com.wishurgift.service.dto.request.WishlistRequestDTO;
import com.wishurgift.service.dto.transformer.UserTransformer;
import com.wishurgift.service.dto.transformer.WishlistTransformer;
import com.wishurgift.utils.StringUtils;
import com.wishurgift.wrapper.Page;
import com.wishurgift.wrapper.Result;

import javax.ejb.Stateless;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;

@Stateless
public class WishlistServiceBean implements WishlistService {

    @Inject
    private WishlistRepository repository;

    @Inject
    private UserRepository userRepository;

    @Inject
    private SharedRepository sharedRepository;

    @Inject
    private ElementService elementService;

    @Override
    public WishlistHeaderDTO add(UserDTO principal, WishlistRequestDTO request) {
        // Recup utilisateur en base
        Optional<User> optionalUser = userRepository.findById(principal.getId());
        if (!optionalUser.isPresent()) {
            return null;
        }
        User user = optionalUser.get();
        // Creation liste de souhait
        Wishlist wishlist = new Wishlist();
        wishlist.setName(request.getName());
        wishlist.setPublic(request.isPublic());
        wishlist.setUser(user);
        repository.insert(wishlist);
        return WishlistTransformer.entityToHeaderDto(wishlist);
    }

    @Override
    public Result update(UserDTO principal, long id, WishlistRequestDTO request) {
        // Récuperation liste en base
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).build();
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possede bien la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return Result.error().data(Result.Error.UNAUTHORIZED).build();
        }
        // MaJ de l'objet
        if (StringUtils.isNotBlank(request.getName())) {
            wishlist.setName(request.getName());
        }
        if (request.isPublic() != null) {
            wishlist.setPublic(request.isPublic());
        }
        repository.update(wishlist);
        return Result.success(WishlistHeaderDTO.class).data(WishlistTransformer.entityToHeaderDto(wishlist)).build();
    }

    @Override
    public Result remove(UserDTO principal, long id) {
        // Récuperation liste en base
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).build();
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possede bien la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return Result.error().data(Result.Error.UNAUTHORIZED).build();
        }
        // Suppr de l'objet
        repository.delete(wishlist);
        return Result.success().build();
    }

    @Override
    public WishlistDTO getById(long id) {
        return WishlistTransformer.entityToDto(repository.getById(id));
    }

    @Override
    public WishlistHeaderDTO getHeaderById(long id) {
        return WishlistTransformer.entityToHeaderDto(repository.getById(id));
    }

    @Override
    public WishlistDTO getWishlist(long id, UserDTO userDTO) {
        // Si on ne connait pas l'utilisateur
        if (userDTO == null) {
            // Recuperation de la liste et vérification si elle est publique
            WishlistDTO wishlist = getById(id);
            if (wishlist == null) {
                return null;
            }
            if (wishlist.isPublic()) {
                return wishlist;
            }
        }
        // Si on connait l'utilisateur
        else {
            // Récupération utilisateur
            Optional<User> optionalUser = userRepository.findById(userDTO.getId());
            if (!optionalUser.isPresent()) {
                return null;
            }
            User user = optionalUser.get();
            // On recherche avec l'utilisateur
            Optional<Wishlist> optionalWishlist = repository.findWishlist(id, user);
            if (optionalWishlist.isPresent()) {
                Wishlist wishlist = optionalWishlist.get();
                WishlistDTO wishlistDTO = WishlistTransformer.entityToDto(wishlist);
                // Si c'est le proprietaire
                if (user.getId() == wishlist.getUser().getId()) {
                    // Ajout liste des personnes avec qui la liste est partagées
                    List<User> users = repository.sharedWith(wishlist);
                    if (users != null) {
                        wishlistDTO.setShared(UserTransformer.entityToLightDto(users));
                    }
                }
                return wishlistDTO;
            }
        }
        return null;
    }

    @Override
    public boolean share(UserDTO principal, long id, long idUser) {
        // Récuperation liste en base
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return false;
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possede bien la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return false;
        }
        // Récupèration de l'autre utilisateur en base
        Optional<User> optionalUser = userRepository.findById(idUser);
        if (!optionalUser.isPresent()) {
            return false;
        }
        User user = optionalUser.get();
        // Regarde si ie partage n'est pas déjà actif
        Optional<Shared> optionalShared = sharedRepository.findShared(wishlist, user);
        if (optionalShared.isPresent()) {
            return false;
        }
        // Partage
        Shared shared = new Shared();
        shared.setWishlist(wishlist);
        shared.setUser(user);
        sharedRepository.insert(shared);
        return true;
    }

    @Override
    public boolean unshare(UserDTO principal, long id, long idUser) {
        // Récuperation liste en base
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return false;
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possede bien la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return false;
        }
        // Récupèration de l'autre utilisateur en base
        Optional<User> optionalUser = userRepository.findById(idUser);
        if (!optionalUser.isPresent()) {
            return false;
        }
        User user = optionalUser.get();
        // Recuperation du partage
        Optional<Shared> optionalShared = sharedRepository.findShared(wishlist, user);
        if (!optionalShared.isPresent()) {
            return false;
        }
        Shared shared = optionalShared.get();
        // Supprime
        sharedRepository.delete(shared);
        return true;
    }

    @Override
    public ElementDTO addElement(UserDTO principal, long id, ElementRequestDTO request) {
        // Récupération de la liste
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return null;
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possède la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return null;
        }
        // Ajout de l'element
        return elementService.add(wishlist, request);
    }

    @Override
    public Page<UserLightDTO> sharedWith(UserDTO principal, long id) {
        // Récupération de la liste
        Optional<Wishlist> optionalWishlist = repository.findById(id);
        if (!optionalWishlist.isPresent()) {
            return null;
        }
        Wishlist wishlist = optionalWishlist.get();
        // Verification que l'utilisateur possède la liste
        if (principal.getId() != wishlist.getUser().getId()) {
            return null;
        }
        // Récupération liste d'utilisateur
        List<User> users = repository.sharedWith(wishlist);
        return Page.unpaged(UserTransformer.entityToLightDto(users));
    }
}
