package com.inspect.system.service.impl;

import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.utils.SpringUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.common.aspect.annotation.DataScope;
import com.inspect.common.security.utils.SecurityUtils;
import com.inspect.system.base.domain.SysRole;
import com.inspect.system.base.domain.SysUser;
import com.inspect.system.domain.SysRoleDept;
import com.inspect.system.domain.SysRoleMenu;
import com.inspect.system.domain.SysUserRole;
import com.inspect.system.mapper.SysRoleDeptMapper;
import com.inspect.system.mapper.SysRoleMapper;
import com.inspect.system.mapper.SysRoleMenuMapper;
import com.inspect.system.mapper.SysUserRoleMapper;
import com.inspect.system.service.ISysRoleService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SysRoleServiceImpl implements ISysRoleService {
    private final SysRoleMapper roleMapper;
    private final SysRoleMenuMapper roleMenuMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final SysRoleDeptMapper roleDeptMapper;

    public SysRoleServiceImpl(SysRoleMapper roleMapper, SysRoleMenuMapper roleMenuMapper, SysUserRoleMapper userRoleMapper, SysRoleDeptMapper roleDeptMapper) {
        this.roleMapper = roleMapper;
        this.roleMenuMapper = roleMenuMapper;
        this.userRoleMapper = userRoleMapper;
        this.roleDeptMapper = roleDeptMapper;
    }

    @DataScope(
            deptAlias = "d"
    )
    public List<SysRole> selectRoleList(SysRole role) {
        return this.roleMapper.selectRoleList(role);
    }

    public List<SysRole> selectRolesByUserId(Long userId) {
        List<SysRole> userRoles = this.roleMapper.selectRolePermissionByUserId(userId);
        List<SysRole> roles = this.selectRoleAll();
        for (SysRole role : roles) {
            for (SysRole userRole : userRoles) {
                if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
                    role.setFlag(true);
                    break;
                }
            }
        }

        return roles;

    }

    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<SysRole> perms = this.roleMapper.selectRolePermissionByUserId(userId);
        Set<String> permsSet = new HashSet<>();

        for (SysRole perm : perms) {
            if (StringUtils.isNotNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(StringUtils.COMMA)));
            }
        }

        return permsSet;
    }

    public List<SysRole> selectRoleAll() {
        return ((SysRoleServiceImpl) SpringUtils.getAopProxy(this)).selectRoleList(new SysRole());
    }

    public List<Long> selectRoleListByUserId(Long userId) {
        return this.roleMapper.selectRoleListByUserId(userId);
    }

    public SysRole selectRoleById(Long roleId) {
        return this.roleMapper.selectRoleById(roleId);
    }

    public String checkRoleNameUnique(SysRole role) {
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = this.roleMapper.checkRoleNameUnique(role.getRoleName());
        return StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue() ? "1" : "0";
    }

    public String checkRoleKeyUnique(SysRole role) {
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = this.roleMapper.checkRoleKeyUnique(role.getRoleKey());
        return StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue() ? "1" : "0";
    }

    public void checkRoleAllowed(SysRole role) {
        if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) {
            throw new ServiceException("不允许操作超级管理员角色");
        }
    }

    public void checkRoleDataScope(Long roleId) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysRole role = new SysRole();
            role.setRoleId(roleId);
            List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
            if (StringUtils.isEmpty(roles)) {
                throw new ServiceException("没有权限访问角色数据！");
            }
        }

    }

    public int countUserRoleByRoleId(Long roleId) {
        return this.userRoleMapper.countUserRoleByRoleId(roleId);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int insertRole(SysRole role) {
        this.roleMapper.insertRole(role);
        return this.insertRoleMenu(role);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int updateRole(SysRole role) {
        this.roleMapper.updateRole(role);
        this.roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
        return this.insertRoleMenu(role);
    }

    public int updateRoleStatus(SysRole role) {
        return this.roleMapper.updateRole(role);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int authDataScope(SysRole role) {
        this.roleMapper.updateRole(role);
        this.roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId());
        return this.insertRoleDept(role);
    }

    public int insertRoleMenu(SysRole role) {
        int rows = 1;
        List<SysRoleMenu> list = new ArrayList<>();
        Long[] menuIds = role.getMenuIds();

        for (Long menuId : menuIds) {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(role.getRoleId());
            rm.setMenuId(menuId);
            list.add(rm);
        }

        if (!list.isEmpty()) {
            rows = this.roleMenuMapper.batchRoleMenu(list);
        }

        return rows;
    }

    public int insertRoleDept(SysRole role) {
        int rows = 1;
        List<SysRoleDept> list = new ArrayList<>();
        Long[] deptIds = role.getDeptIds();
        for (Long deptId : deptIds) {
            SysRoleDept rd = new SysRoleDept();
            rd.setRoleId(role.getRoleId());
            rd.setDeptId(deptId);
            list.add(rd);
        }

        if (!list.isEmpty()) {
            rows = this.roleDeptMapper.batchRoleDept(list);
        }

        return rows;
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int deleteRoleById(Long roleId) {
        this.roleMenuMapper.deleteRoleMenuByRoleId(roleId);
        this.roleDeptMapper.deleteRoleDeptByRoleId(roleId);
        return this.roleMapper.deleteRoleById(roleId);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int deleteRoleByIds(Long[] roleIds) {
        for (Long roleId : roleIds) {
            this.checkRoleAllowed(new SysRole(roleId));
            this.checkRoleDataScope(roleId);
            SysRole role = this.selectRoleById(roleId);
            if (this.countUserRoleByRoleId(roleId) > 0) {
                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }

        this.roleMenuMapper.deleteRoleMenu(roleIds);
        this.roleDeptMapper.deleteRoleDept(roleIds);
        return this.roleMapper.deleteRoleByIds(roleIds);
    }

    public int deleteAuthUser(SysUserRole userRole) {
        return this.userRoleMapper.deleteUserRoleInfo(userRole);
    }

    public int deleteAuthUsers(Long roleId, Long[] userIds) {
        return this.userRoleMapper.deleteUserRoleInfos(roleId, userIds);
    }

    public int insertAuthUsers(Long roleId, Long[] userIds) {
        List<SysUserRole> list = new ArrayList<>();
        for (Long userId : userIds) {
            SysUserRole ur = new SysUserRole();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            list.add(ur);
        }

        return this.userRoleMapper.batchUserRole(list);
    }
}
