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.vo.RoleVO;
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 javax.persistence.criteria.SetJoin;
import java.util.List;
import java.util.stream.Collectors;

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

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

    @Override
    public List<Role> findAll() {
        return roleRepository.findAll();
    }

    @Override
    public Role findById(int id) {
        return roleRepository.findById(id).orElse(null);
    }

    @Override
    public Role findByName(String name) {
        return roleRepository.findByName(name);
    }

    @Override
    public Page<RoleVO> getRoleVOByPage(PageRequest pageRequest) {
        return roleRepository.findAll(pageRequest).map(RoleVO::new);
    }

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

    @Override
    public RoleVO getRoleVOById(Integer id) {
        Role role = findById(id);
        return role != null ? new RoleVO(role) : null;
    }

    /**
     * 获取拥有角色的用户
     *
     * @param
     * @return
     * @date 2021-07-14 下午2:57
     */
    @Override
    public List<User> getUsersByRoleId(Integer id) {
        Role role = findById(id);
        return getUsersByRole(role);
    }

    /**
     * SQL 语句
     * select u.*
     * from role r
     * inner join user_role ur
     * inner join `user` u
     * on r.title=ur.role and ur.user_id=u.id and r.title='ROLE_FRONTEND'
     *
     * @param
     * @return
     * @date 2023-03-02 17:54:48
     */
    @Override
    public List<User> getUsersByRole(Role role) {
        String name = role.getName();
        Specification<User> specification = ((root, query, cb) -> {
            SetJoin<User, String> setJoin = root.joinSet("role");
            // User 中 Set 的元素是原始类型
            Predicate predicate = setJoin.as(String.class).in(name);
            // User 中的 Set 的元素是某个对象, fieldName 表示对象的某个字段名
            //Predicate predicate = cb.equal(setJoin.get("fieldName"), title);
            return cb.and(predicate);
        });

        return userRepository.findAll(specification);
    }
}
