package com.zsc.edu.gateway.framework.security;

import com.zsc.edu.gateway.common.util.TreeUtil;
import com.zsc.edu.gateway.exception.StateException;
import com.zsc.edu.gateway.modules.system.entity.*;
import com.zsc.edu.gateway.modules.system.repo.*;
import com.zsc.edu.gateway.modules.system.service.DeptService;
import com.zsc.edu.gateway.modules.system.service.RoleService;
import com.zsc.edu.gateway.modules.system.service.impl.RoleServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author harry_yao
 */
@AllArgsConstructor
@Service
public class JpaUserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepo;
    private  final AuthorityRepository authorityRepository;
    private final MenuRepository menuRepository;
    private final DeptService deptService;
    private final RoleRepository roleRepository;
    private final RoleService roleService;
    private final UserRolesRepository userRolesRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepo.selectByUsername(username);
        if (!user.getEnableState()) {
            throw new StateException("用户 '" + username + "' 已被禁用！请联系管理员");
        }
        List<Long> roleIds = userRolesRepository.selectByUserId(user.getId());
        List<Role> roles = roleRepository.selectByIds(roleIds);
        user.setRoles(roles);
        List<Dept> depts = deptService.listTree(user.deptId);
        List<Dept> flat = TreeUtil.flat(depts, Dept::getChildren, d -> d.setChildren(null));
        Set<Long> dataScopeDeptIds = flat.stream().map(Dept::getId).collect(Collectors.toSet());
        user.setDataScopeDeptIds(dataScopeDeptIds);
//        List<RoleAuthority> roleAuthorities= roleAuthoritiesRepository.selectByRoleId(user.getRoleId());
//        user.role.authorities = authorityRepository.selectAuthoritiesByRoleId(user.getRoleId());
        List<Menu> menus = menuRepository.selectByRoleId(user.getRoleId());
        Set<String> permissions = menus.stream().map(Menu::getPermissions).collect(Collectors.toSet());
        return UserDetailsImpl.from(user, permissions);
    }
}
