class RepositoryUserAccessService implements UserAccessService {

    @Override
    public User giveUserAccessUntil(User user, LocalDateTime until) throws IllegalArgumentException {
        if(until.isBefore(LocalDateTime.now(clock))) {
            throw new IllegalArgumentException("End date must lie in the future!");
        }

        var latestIntervalOptional = user.getLatestAccessInterval();

        if(latestIntervalOptional.isEmpty() || !userHasActiveAccessInterval(user)) {
            var interval = new AccessInterval(user, LocalDateTime.now(clock), until);
            user.addAccessInterval(interval);

            userAccessEventHandler.onAccessCreated(user, interval);

            return userService.save(user);
        } else {
            var latestInterval = latestIntervalOptional.get();
            var oldEndTime = latestInterval.getEndTime();
            if(oldEndTime.isEqual(until)) {
                return user;
            }

            latestInterval.setEndTime(until);
            intervalRepo.save(latestInterval);

            userAccessEventHandler.onAccessChanged(user, latestInterval, oldEndTime);
        }

        return user;
    }

    @Autowired public  RepositoryUserAccessService(RepositoryUserService userService,
                                       AccessIntervalRepository intervalRepo,
                                       UserAccessEventHandler userAccessEventHandler,
                                       Clock clock);

}