
package com.tmerclub.cloud.rbac.service.impl;

import com.tmerclub.cloud.api.rbac.bo.UriPermissionBO;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.util.CacheManagerUtil;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.rbac.dto.MenuPermissionDTO;
import com.tmerclub.cloud.rbac.mapper.MenuPermissionMapper;
import com.tmerclub.cloud.rbac.model.MenuPermission;
import com.tmerclub.cloud.rbac.service.MenuPermissionService;
import com.tmerclub.cloud.rbac.vo.MenuPermissionVO;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

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

/**
 * 菜单资源
 *
 * @author tmerclub
 * @date 2020-09-14 16:27:55
 */
@Service
public class MenuPermissionServiceImpl implements MenuPermissionService {

    @Autowired
    private MenuPermissionMapper menuPermissionMapper;

    @Autowired
    private CacheManagerUtil cacheManagerUtil;

    @Override
    public PageVO<MenuPermissionVO> page(PageDTO pageDTO, MenuPermissionDTO menuPermissionDTO) {
        return PageUtil.doPage(pageDTO, () -> menuPermissionMapper.list(menuPermissionDTO));
    }

    @Override
    public MenuPermissionVO getByMenuPermissionId(Long menuPermissionId) {
        return menuPermissionMapper.getByMenuPermissionId(menuPermissionId);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.URI_PERMISSION_KEY, key = "#menuPermission.bizType")
    public ServerResponseEntity<Void> save(MenuPermission menuPermission) {

        MenuPermission dbMenuPermission = menuPermissionMapper.getByPermission(menuPermission.getPermission(),
                menuPermission.getBizType(), menuPermission.getMenuPermissionId());
        menuPermissionMapper.save(menuPermission);
        return ServerResponseEntity.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.URI_PERMISSION_KEY, key = "#menuPermission.bizType")
    public ServerResponseEntity<Void> update(MenuPermission menuPermission) {
        MenuPermission dbMenuPermission = menuPermissionMapper.getByPermission(menuPermission.getPermission(),
                menuPermission.getBizType(), menuPermission.getMenuPermissionId());
        menuPermissionMapper.update(menuPermission);
        return ServerResponseEntity.success();
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.URI_PERMISSION_KEY, key = "#sysType")
    public void deleteById(Long menuPermissionId, Integer sysType) {
        menuPermissionMapper.deleteById(menuPermissionId, sysType);
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = CacheNames.USER_PERMISSIONS_KEY, key = "#sysType + ':' + #userId"),
            @CacheEvict(cacheNames = CacheNames.MENU_ID_LIST_KEY, key = "#userId")
    })
    public void clearUserPermissionsCache(Long userId, Integer sysType) {
    }

    @Override
    public List<String> listUserPermissions(Long userId, Integer sysType, boolean isAdmin) {
        MenuPermissionServiceImpl menuPermissionService = (MenuPermissionServiceImpl) AopContext.currentProxy();
        List<String> permsList;

        // 系统管理员，拥有最高权限
        if (isAdmin) {
            List<UriPermissionBO> uriPermissions = listUriPermissionInfo(sysType);
            permsList = uriPermissions.stream().map(UriPermissionBO::getPermission).collect(Collectors.toList());
        }
        else {
            List<UriPermissionBO> uriPermissionBOList = menuPermissionService.listPermissionByUserIdAndSysType(userId, sysType);
            permsList = uriPermissionBOList.stream()
                    .filter(uriPermissionBO -> uriPermissionBO.getHasPermission())
                    .map(UriPermissionBO::getPermission).collect(Collectors.toList());
        }
        return permsList;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.URI_PERMISSION_KEY, key = "#sysType")
    public List<UriPermissionBO> listUriPermissionInfo(Integer sysType) {
        return menuPermissionMapper.listUriPermissionInfo(sysType);
    }

    @Override
    public List<MenuPermissionVO> listByMenuId(Long menuId) {
        return menuPermissionMapper.listByMenuId(menuId);
    }

    /**
     * 获取某个类型用户的所有权限列表（有缓存）
     *
     * @param sysType 系统类型
     * @return 权限列表
     */
    @Cacheable(cacheNames = CacheNames.PERMISSIONS_KEY, key = "#sysType")
    public List<String> listAllPermission(Integer sysType) {
        return menuPermissionMapper.listAllPermissionBySysType(sysType);
    }

    /**
     * 获取某个类型用户的所有权限列表（有缓存）
     *
     * @param sysType 系统类型
     * @return 权限列表
     */
    @Override
    @Cacheable(cacheNames = CacheNames.USER_PERMISSIONS_KEY, key = "#sysType + ':' + #userId")
    public List<UriPermissionBO> listPermissionByUserIdAndSysType(Long userId, Integer sysType) {
        // 获取所有的权限，并标出该用户所拥有的权限
        List<String> userPermissionList = menuPermissionMapper.listPermissionByUserIdAndSysType(userId, sysType);

        MenuPermissionServiceImpl menuPermissionService = (MenuPermissionServiceImpl)AopContext.currentProxy();
        List<UriPermissionBO> uriPermissions = menuPermissionService.listUriPermissionInfo(sysType);
        for (UriPermissionBO uriPermission : uriPermissions) {
            if (!userPermissionList.contains(uriPermission.getPermission())) {
                uriPermission.setHasPermission(false);
            }
        }
        return uriPermissions;
    }

    @Override
    public List<UriPermissionBO> getUriPermissionListByMenuPermIdList(List<Long> menuIdList) {
        return menuPermissionMapper.getUriPermissionListByMenuPermIdList(menuIdList);
    }
}
