package com.chushang.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chushang.common.core.exception.ResultException;
import com.chushang.common.core.util.SpringUtils;
import com.chushang.common.core.util.StringUtils;
import com.chushang.common.core.web.AjaxResult;
import com.chushang.common.mybatis.utils.PageResult;
import com.chushang.datascope.annotation.DataScope;
import com.chushang.datascope.entity.DataScopeEntity;
import com.chushang.security.utils.SecurityUtils;
import com.chushang.system.mapper.SysRoleMapper;
import com.chushang.system.service.ISysRoleMenuService;
import com.chushang.system.entity.bo.CancelUserRole;
import com.chushang.system.entity.dto.ListRoleDTO;
import com.chushang.system.entity.po.SysRole;
import com.chushang.system.entity.po.SysUser;
import com.chushang.security.entity.vo.LoginUser;
import com.chushang.system.service.ISysRoleDeptService;
import com.chushang.system.service.ISysRoleService;
import com.chushang.system.service.ISysUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 角色用于控制菜单 及 用户的显示 服务实现类
 * </p>
 *
 * @author author
 * @since 2022-08-18
 */
@Slf4j
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    ISysRoleMenuService roleMenuService;
    @Autowired
    ISysRoleDeptService roleDeptService;
    @Autowired
    ISysUserRoleService userRoleService;

    @Override
    @DataScope(deptAlias = "d")
    public List<SysRole> selectRoleAll(SysRole sysRole) {
        return baseMapper.selectRoleList(sysRole);
    }

    @Override
    public List<SysRole> selectRolesByUserId(SysUser user) {
        // 当前用户的角色
        List<SysRole> userRoles = user.getRoles();
        // 当前登录用户的所有角色 -->
        List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleAll(new SysRole());
        for (SysRole role : roles) {
            for (SysRole userRole : userRoles) {
                if (Objects.equals(role.getRoleId(), userRole.getRoleId())) {
                    role.setFlag(true);
                    break;
                }
            }
        }
        return roles;
    }

    @Override
    @DataScope(deptAlias = "d")
    public AjaxResult selectRoleList(ListRoleDTO listRole) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<SysRole> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(listRole.getPage(), listRole.getLimit());
        List<SysRole> listAfDataVOList = baseMapper.listRole(listRole, page);

        return AjaxResult.success(new PageResult(
                listAfDataVOList,
                page.getTotal(),
                page.getPages(),
                page.getCurrent()));
    }

    @Override
    @DataScope(deptAlias = "d")
    public void checkRoleDataScope(SysRole role) {
        // 登录用户非管理员时进行判断 , 判断当前登录用户的角色是否包含以下角色
        if (!SecurityUtils.isAdmin()) {
            List<SysRole> roles = baseMapper.selectRoleList(role);
            if (CollectionUtil.isEmpty(roles)) {
                throw new ResultException("没有权限访问角色数据！");
            }
        }
    }

    @Override
    public SysRole selectRoleById(Long roleId) {
        return baseMapper.selectRoleById(roleId);
    }

    @Override
    @Transactional
    public void saveRole(SysRole role) {
        LoginUser<SysUser, DataScopeEntity> loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        Long deptId = sysUser.getDeptId();

        role.setDeptId(deptId);
        save(role);

        roleMenuService.saveBatch(role.getRoleId(), role.getMenuIds());
    }

    @Override
    @Transactional
    public void updateRole(SysRole role) {
        updateById(role);

        roleMenuService.saveBatch(role.getRoleId(), role.getMenuIds());
    }

    @Override
    @Transactional
    public void authDataScope(SysRole role) {
        // 修改角色信息
        updateById(role);
        // 删除角色与部门关联
        roleDeptService.saveBatch(role.getRoleId(), role.getDeptIds());
    }

    @Override
    @Transactional
    public void deleteRoleByIds(Long[] roleIds) {
        for (Long roleId : roleIds) {
            SysRole sysRole = new SysRole(roleId);
            if (2 == roleId){
               continue;
            }
            checkRoleAllowed(sysRole);

            SpringUtils.getAopProxy(this).checkRoleDataScope(sysRole);

            SysRole role = selectRoleById(roleId);

            if (userRoleService.countUserRoleByRoleId(roleId) > 0) {
                throw new ResultException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }
        // 删除角色与菜单关联
        roleMenuService.deleteRoleMenu(Arrays.asList(roleIds));
        // 删除角色与部门关联
        roleDeptService.deleteRoleDept(Arrays.asList(roleIds));
        // 删除角色
        baseMapper.deleteBatchIds(Arrays.asList(roleIds));
    }

    @Override
    public void deleteAuthUser(CancelUserRole cancelUserRole) {
        userRoleService.removeByUserIdAndRoleId(
                Set.of(cancelUserRole.getUserIds()),
                cancelUserRole.getRoleId());
    }

    @Override
    public void insertAuthUsers(Long roleId, Long[] userIds) {
        userRoleService.saveOrUpdate(userIds, roleId);
    }

    @Override
    public String selectRolesByUserName(String username) {
        Set<SysRole> roleList = baseMapper.selectRoleByUsername(username);
        return CollectionUtil.isEmpty(roleList) ? StringUtils.EMPTY : roleList.stream().map(SysRole::getRoleName)
                .collect(Collectors.joining(","));
    }
}
