class MovieServiceImpl implements MovieService {

    @Override
    public MovieDto updateMovie(final MovieDto movieDto) throws MovieNotFoundException, MovieConditionalException {
        try {
            final Movie movie = movieRepository.findById(movieDto.getId().toString())
                .orElseThrow(() -> new MovieNotFoundException());
            if (movie.isDeleted()) {
                throw new MovieNotFoundException();
            }

            movieDto.setUpdateTimestamp(Instant.now());

            final Movie updatedMovie = movieMapper.movieDtoToMovie(movieDto);
            updatedMovie.setRevision(UUID.randomUUID().toString());
            updatedMovie.setTotalLikes(movie.getTotalLikes());
            updatedMovie.setUpdated(true);
            updatedMovie.setDeleted(movie.isDeleted());
            updatedMovie.setPendingLikes(movie.getPendingLikes());
            updatedMovie.setPendingUnlikes(movie.getPendingUnlikes());

            final long affectedDocuments = movieRepository.updateMovie(updatedMovie, movie.getRevision());
            if (affectedDocuments == 0) {
                throw new MovieConditionalException();
            }

            movieIndexHelper.indexMovie(movie);
        }
        catch (final MovieNotFoundException | MovieConditionalException ex) {
            throw ex;
        }
        catch (final Exception ex) {
            final String errorMessage = String.format("An error occured while updating movie %s: %s", movieDto.getId(),
                ex.getMessage());

            log.error(errorMessage, ex);
            throw new MoviePersistenceException(errorMessage, ex);
        }

        return movieDto;
    }

}