package cn.reghao.oss.console.account.db.query;

import cn.reghao.oss.console.account.db.repository.RoleRepository;
import cn.reghao.oss.console.account.db.repository.UserRepository;
import cn.reghao.oss.console.account.model.po.Role;
import cn.reghao.oss.console.account.model.po.User;
import cn.reghao.oss.console.account.model.po.UserAuthority;
import cn.reghao.oss.console.account.model.vo.UserVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2021-07-12 15:32:26
 */
@Service
public class UserQueryImpl implements UserQuery {
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;

    public UserQueryImpl(UserRepository userRepository, RoleRepository roleRepository) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    @Override
    public User findById(int id) {
        return userRepository.getOne(id);
    }

    @Override
    public Page<UserVO> getUserVOByPage(PageRequest pageRequest) {
        return userRepository.findAll(pageRequest).map(UserVO::new);
    }

    @Override
    public List<UserVO> getByMatchScreenName(String screenName) {
        Specification<User> specification = (root, query, cb) -> {
            String likeQuery = String.format("%%%s%%", screenName);
            Predicate predicate = cb.like(root.get("screenName"), likeQuery);
            return cb.and(predicate);
        };
        return userRepository.findAll(specification).stream().map(UserVO::new).collect(Collectors.toList());
    }

    /**
     * 获取用户拥有的角色
     *
     * @param
     * @return
     * @date 2021-09-10 下午11:12
     */
    @Override
    public Set<Role> getUserRoles(User user) {
        Set<UserAuthority> set = user.getAuthorities().stream()
                .map(grantedAuthority -> new UserAuthority(grantedAuthority.getAuthority()))
                .collect(Collectors.toSet());

        List<String> roles = set.stream()
                .map(UserAuthority::getAuthority)
                .collect(Collectors.toList());
        Specification<Role> spec = ((root, query, criteriaBuilder) -> root.get("name").in(roles));
        return new HashSet<>(roleRepository.findAll(spec));
    }

    @Override
    public Set<Role> getUserRoles(Integer userId) {
        User user = findById(userId);
        if (user == null) {
            return Collections.emptySet();
        }

        return getUserRoles(user);
    }
}
