package com.qiaoba.module.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.entity.LoginUser;
import com.qiaoba.auth.entity.SecurityUser;
import com.qiaoba.auth.entity.dto.RoleDto;
import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.service.SysMenuService;
import com.qiaoba.module.system.service.SysUserRoleService;
import com.qiaoba.module.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
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 java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户权限验证处理
 *
 * @author ailanyin
 * @version 1.0
 * @since 2022-09-22 04:20:28
 */
@Service
@RequiredArgsConstructor
public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDetailsApiService {

    private final SysUserService sysUserService;
    private final SysMenuService sysMenuService;
    private final SysUserRoleService sysUserRoleService;
    private final RedisService redisService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
        return Objects.isNull(user) ? null : new LoginUser(user.getDeviceSn(), user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions());
    }


    private UserDetails createUserDetails(SysUser user, String deviceSn) {
        Set<String> perms = sysMenuService.selectPermsByUserId(user.getUserId());
        List<RoleDto> roles = sysUserRoleService.selectRoleDtoByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
        List<String> roleKeys = roles.stream().map(RoleDto::getRoleKey).collect(Collectors.toList());
        return new LoginUser(deviceSn, user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roles, roleKeys, perms);
    }

    @Override
    public UserDetails toCache(String username, String deviceSn) {
        SysUser user = sysUserService.selectByUsername(username);
        UserDetails details = createUserDetails(user, deviceSn);
        SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
        redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.expireTime * 3600);
        return details;
    }

    @Override
    public void deleteCache(String username, String deviceSn) {
        SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
        if (Objects.nonNull(user) && deviceSn.equals(user.getDeviceSn())) {
            redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username);
        }
    }
}
