package cn.reghao.bnt.web.admin.service.impl;

import cn.reghao.bnt.web.admin.db.repository.MenuRepository;
import cn.reghao.bnt.web.admin.model.po.Menu;
import cn.reghao.bnt.web.admin.model.po.Role;
import cn.reghao.bnt.web.admin.model.po.User;
import cn.reghao.bnt.web.admin.db.repository.RoleRepository;
import cn.reghao.bnt.web.admin.model.po.UserAuthority;
import cn.reghao.bnt.web.admin.model.vo.RoleVO;
import cn.reghao.bnt.web.admin.service.AccountService;
import cn.reghao.bnt.web.admin.service.RoleService;
import lombok.extern.slf4j.Slf4j;
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 jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.SetJoin;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2020-06-19 16:36:53
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {
    private final RoleRepository roleRepository;
    private final MenuRepository menuRepository;
    private final AccountService accountService;
    private final int pageSize = 100;

    public RoleServiceImpl(RoleRepository roleRepository, MenuRepository menuRepository, AccountService accountService) {
        this.roleRepository = roleRepository;
        this.menuRepository = menuRepository;
        this.accountService = accountService;
    }

    @Override
    public void updateRoleMenus(Integer roleId, Set<Integer> menuIds) {
        Set<Menu> menus = new HashSet<>(menuRepository.findAllById(menuIds));
        Role role = roleRepository.getOne(roleId);
        role.setMenus(menus);
        roleRepository.save(role);
    }

    @Override
    public List<RoleVO> getAllRoles() {
        PageRequest pageRequest = PageRequest.of(0, pageSize);
        return roleRepository.findAll(pageRequest).stream()
                .map(role -> {
                    int total = accountService.countUsersByRole(role.getId());
                    return new RoleVO(role, total);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Role> getRolesByUser(Integer userId) {
        User user = accountService.getById(userId);
        if (user == null) {
            return Collections.emptyList();
        }

        List<String> roles = new ArrayList<>(user.getRole());
        Specification<Role> spec = ((root, query, criteriaBuilder) -> root.get("name").in(roles));
        return roleRepository.findAll(spec);
    }
}
