package ankios.blog.service;

import ankios.blog.model.Role;
import ankios.blog.model.User;
import ankios.blog.repository.RoleRepository;
import ankios.blog.repository.UserRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userRepository.findByUsernameOrEmail(s, s);

        if (user == null)
            throw new UsernameNotFoundException("no such user");

        List<GrantedAuthority> authorities = new ArrayList<>();
        for (Role role : user.getRoles()) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
                user.isEnabled(), true, true, true, authorities);
    }

    @Override
    public User findByEmail(String email) {
        return userRepository.findByEmailIgnoreCase(email);
    }

    @Override
    public User findByUsername(String username) {
        return userRepository.findByUsernameIgnoreCase(username);
    }

    @Override
    public boolean usernameExists(String username) {
        return findByUsername(username) != null;
    }

    @Override
    public boolean emailExists(String email) {
        return findByEmail(email) != null;
    }

    @Override
    public void register(User user) {
        if(user==null){
         return;
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        user.getRoles().add(roleRepository.findByName("ROLE_USER"));

        user.setEnabled(true);

        user.setRegistrationDate(LocalDateTime.now());

        userRepository.saveAndFlush(user);
    }

    @Override
    public void changeEmail(String newEmail, String currentPassword) throws AuthException {
        User user = currentUser();
        if (!passwordEncoder.matches(currentPassword, user.getPassword()))
            throw new AuthException("password does not match");

        user.setEmail(newEmail);

        userRepository.saveAndFlush(user);
    }

    @Override
    public void changePassword(String newPassword, String currentPassword) throws AuthException {
        User user = currentUser();

        if (!passwordEncoder.matches(currentPassword, user.getPassword()))
            throw new AuthException("password does not match");

        user.setPassword(passwordEncoder.encode(newPassword));

        userRepository.saveAndFlush(user);
    }

    @Override
    public void changeProfileInfo(User newProfileInfo) {
        User user = currentUser();

        user.setAboutText(newProfileInfo.getAboutText());

        user.setWebsiteLink(newProfileInfo.getWebsiteLink());

        userRepository.saveAndFlush(user);
    }

    @Override
    public void changeAvatar(UploadedAvatarInfo uploadedAvatarInfo) {
        User user = currentUser();

        user.setBigAvatarLink(uploadedAvatarInfo.bigImageLink);

        user.setSmallAvatarLink(uploadedAvatarInfo.smallImageLink);

        userRepository.saveAndFlush(user);
    }

    @Override
    public void removeAvatar() {
        User user = currentUser();

        user.setBigAvatarLink(null);

        user.setSmallAvatarLink(null);

        userRepository.saveAndFlush(user);
    }

    @Override
    public void authenticate(User user) {
        UserDetails userDetails = loadUserByUsername(user.getUsername());

        Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
    }

    @Override
    public boolean isAuthenticated() {
        SecurityContext securityContext = SecurityContextHolder.getContext();

        Authentication auth = securityContext.getAuthentication();

        return auth != null && !(auth instanceof AnonymousAuthenticationToken) && auth.isAuthenticated();
    }

    @Override
    public boolean isAdmin() {
        User user = currentUser();

        return user != null && user.hasRole("ROLE_ADMIN");
    }

    @Override
    public User currentUser() {
        if (!isAuthenticated())
            return null;

        SecurityContext securityContext = SecurityContextHolder.getContext();

        Authentication auth = securityContext.getAuthentication();

        return userRepository.findByUsernameIgnoreCase(auth.getName());
    }

    public PasswordEncoder getPasswordEncoder() {
        return passwordEncoder;
    }

    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
}

@@ -3239,32 +3239,50 @@
 d does not match
+. Please try again
 %22);%0D%0A%0D%0A        u

Update UserServiceImpl.java