package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.diagbot.dto.SysMenuPermissionDTO;
import com.diagbot.dto.SysPermissionDTO;
import com.diagbot.dto.SysRoleDTO;
import com.diagbot.dto.SysRoleMenuDTO;
import com.diagbot.entity.SysRole;
import com.diagbot.entity.SysRoleMenu;
import com.diagbot.entity.SysRolePermission;
import com.diagbot.entity.SysUserRole;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.service.impl.SysRoleMenuServiceImpl;
import com.diagbot.service.impl.SysRolePermissionServiceImpl;
import com.diagbot.service.impl.SysRoleServiceImpl;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.DateUtil;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.SysUserUtils;
import com.diagbot.vo.SysMenuSaveVO;
import com.diagbot.vo.SysPermissionSaveVO;
import com.diagbot.vo.SysRoleMenuQueryVO;
import com.diagbot.vo.SysRoleMenuSaveVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: gaodm
 * @time: 2020/4/27 10:13
 */
@Component
public class SysRoleFacade extends SysRoleServiceImpl {
    @Autowired
    @Qualifier("sysRoleMenuServiceImpl")
    private SysRoleMenuServiceImpl sysRoleMenuService;

    @Autowired
    @Qualifier("sysRolePermissionServiceImpl")
    private SysRolePermissionServiceImpl sysRolePermissionService;

    @Autowired
    private SysUserRoleFacade sysUserRoleFacade;

    @Autowired
    private TokenFacade tokenFacade;

    /**
     * 获取角色列表信息
     *
     * @return 角色列表信息
     */
    public List<SysRoleDTO> listFac() {
        List<SysRole> sysRoleList = this.list(new QueryWrapper<SysRole>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .gt("id", -1L)
        );
        return BeanUtil.listCopyTo(sysRoleList, SysRoleDTO.class);
    }

    /**
     * 获取角色下拉列表信息
     *
     * @return 角色下拉列表信息
     */
    public List<SysRoleDTO> listForUser() {
        List<SysRole> sysRoleList = this.list(new QueryWrapper<SysRole>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
        );
        return BeanUtil.listCopyTo(sysRoleList, SysRoleDTO.class);
    }

    /**
     * 获取角色菜权限单等数据
     *
     * @param sysRoleMenuQueryVO 获取角色菜权限单入参
     * @return 是否成功
     */
    public List<SysRoleMenuDTO> getRoleMenu(SysRoleMenuQueryVO sysRoleMenuQueryVO) {
        List<SysMenuPermissionDTO> sysMenuPermissionDTOList = this.getMenuPermission(sysRoleMenuQueryVO);
        List<SysRoleMenuDTO> sysRoleMenuDTOList = new ArrayList<>();
        List<Long> menuId = new ArrayList<>();
        for (SysMenuPermissionDTO sysMenuPermissionDTO : sysMenuPermissionDTOList) {
            if (!menuId.contains(sysMenuPermissionDTO.getMenuId())) {
                menuId.add(sysMenuPermissionDTO.getMenuId());
                SysRoleMenuDTO sysRoleMenuDTO = new SysRoleMenuDTO();
                BeanUtil.copyProperties(sysMenuPermissionDTO, sysRoleMenuDTO);
                sysRoleMenuDTOList.add(sysRoleMenuDTO);
            }
        }
        Map<Long, List<SysMenuPermissionDTO>> menuPermissionMap = EntityUtil.makeEntityListMap(sysMenuPermissionDTOList, "menuId");
        Map<Long, List<SysRoleMenuDTO>> menuMap = EntityUtil.makeEntityListMap(sysRoleMenuDTOList, "parentId");
        List<SysRoleMenuDTO> menuRes = menuMap.get(-1L);
        for (SysRoleMenuDTO bean : menuRes) {
            getSonMenu(bean, menuMap, menuPermissionMap);
        }
        return menuRes;
    }

    /**
     * 递归获取菜单结构
     *
     * @param menu              当前菜单
     * @param menuMap           菜单集
     * @param menuPermissionMap 菜单权限集
     * @return 菜单结构
     */
    public void getSonMenu(SysRoleMenuDTO menu,
                           Map<Long, List<SysRoleMenuDTO>> menuMap,
                           Map<Long, List<SysMenuPermissionDTO>> menuPermissionMap) {
        List<SysRoleMenuDTO> list = menuMap.get(menu.getMenuId());
        List<SysMenuPermissionDTO> listPermission = menuPermissionMap.get(menu.getMenuId());
        if (ListUtil.isNotEmpty(listPermission)) {
            List<SysPermissionDTO> sysPermissionDTOList = new ArrayList<>();
            for (SysMenuPermissionDTO sysMenuPermissionDTO : listPermission) {
                if (null != sysMenuPermissionDTO.getPermissionId()) {
                    SysPermissionDTO sysPermissionDTO = new SysPermissionDTO();
                    BeanUtil.copyProperties(sysMenuPermissionDTO, sysPermissionDTO);
                    sysPermissionDTO.setParentId(menu.getMenuId());
                    sysPermissionDTOList.add(sysPermissionDTO);
                }
            }
            menu.setSysPermissionDTOList(sysPermissionDTOList);
        }
        if (ListUtil.isNotEmpty(list)) {
            menu.setSonMenuDTOList(list);
            for (SysRoleMenuDTO bean : list) {
                getSonMenu(bean, menuMap, menuPermissionMap);
            }
        }
    }

    /**
     * 修改角色菜单权限数据
     *
     * @param sysRoleMenuSaveVO 修改角色菜单权限数据入参
     * @return 是否成功
     */
    public Boolean saveRoleMenu(SysRoleMenuSaveVO sysRoleMenuSaveVO) {
        Date now = DateUtil.now();
        String userId = SysUserUtils.getCurrentPrincipleID();
        //查询该角色的所有用户
        List<Long> userIds = sysUserRoleFacade.list(new QueryWrapper<SysUserRole>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("role_id", sysRoleMenuSaveVO.getRoleId())
        ).stream().distinct().map(SysUserRole::getUserId).collect(Collectors.toList());
        //删除角色菜单和角色权限
        sysRoleMenuService.update(new UpdateWrapper<SysRoleMenu>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("role_id", sysRoleMenuSaveVO.getRoleId())
                .set("is_deleted", IsDeleteEnum.Y.getKey())
                .set("modifier", userId)
                .set("gmt_modified", now)
        );
        sysRolePermissionService.update(new UpdateWrapper<SysRolePermission>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("role_id", sysRoleMenuSaveVO.getRoleId())
                .set("is_deleted", IsDeleteEnum.Y.getKey())
                .set("modifier", userId)
                .set("gmt_modified", now)
        );
        //新增角色菜单和角色权限
        if (ListUtil.isNotEmpty(sysRoleMenuSaveVO.getSysMenuSaveVOList())) {
            List<SysRoleMenu> sysRoleMenuList = new ArrayList<>();
            for (SysMenuSaveVO sysMenuSaveVO : sysRoleMenuSaveVO.getSysMenuSaveVOList()) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setCreator(userId);
                sysRoleMenu.setModifier(userId);
                sysRoleMenu.setGmtCreate(now);
                sysRoleMenu.setGmtModified(now);
                sysRoleMenu.setRoleId(sysRoleMenuSaveVO.getRoleId());
                sysRoleMenu.setMenuId(sysMenuSaveVO.getMenuId());
                sysRoleMenuList.add(sysRoleMenu);
            }
            sysRoleMenuService.saveBatch(sysRoleMenuList);
        }
        if (ListUtil.isNotEmpty(sysRoleMenuSaveVO.getSysPermissionSaveVOList())) {
            List<SysRolePermission> sysRolePermissionList = new ArrayList<>();
            for (SysPermissionSaveVO sysPermissionSaveVO : sysRoleMenuSaveVO.getSysPermissionSaveVOList()) {
                SysRolePermission sysRolePermission = new SysRolePermission();
                sysRolePermission.setCreator(userId);
                sysRolePermission.setModifier(userId);
                sysRolePermission.setGmtCreate(now);
                sysRolePermission.setGmtModified(now);
                sysRolePermission.setRoleId(sysRoleMenuSaveVO.getRoleId());
                sysRolePermission.setPermissionId(sysPermissionSaveVO.getPermissionId());
                sysRolePermissionList.add(sysRolePermission);
            }
            sysRolePermissionService.saveBatch(sysRolePermissionList);
        }
        //清除该角色的所有用户的token缓存
        if (ListUtil.isNotEmpty(userIds)) {
            tokenFacade.deleteBatchToken(userIds);
        }
        return true;
    }
}
