package com.starry.admin.modules.system.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.starry.admin.modules.system.module.entity.SysDeptEntity;
import com.starry.admin.modules.system.module.entity.SysRoleEntity;
import com.starry.admin.modules.system.module.entity.SysUserRoleEntity;
import com.starry.admin.modules.system.service.SysDeptService;
import com.starry.admin.modules.system.service.SysRoleService;
import com.starry.admin.modules.system.service.SysUserService;
import com.starry.admin.modules.system.vo.RoleUserResultVo;
import com.starry.admin.modules.system.vo.SysRoleAddVo;
import com.starry.admin.modules.system.vo.SysUserQueryVo;
import com.starry.common.annotation.Log;
import com.starry.common.constant.UserConstants;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * <p>
 * 角色表 前端控制器
 * </p>
 *
 * @author admin
 * @since 2022-07-01
 */
@Api(tags = "角色管理", description = "系统角色管理相关接口")
@RestController
@RequestMapping("/ucenter/role")
public class SysRoleController {

    @Resource
    private SysRoleService roleService;
    @Resource
    private SysDeptService deptService;
    @Resource
    private SysUserService userService;

    @ApiOperation(value = "添加角色", notes = "创建新的系统角色")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败，角色名称或权限已存在")})
    @PreAuthorize("@customSs.hasPermission('system:role:create')")
    @PostMapping("/create")
    public R create(@ApiParam(value = "角色信息", required = true) @Validated @RequestBody SysRoleAddVo roleAddVo) {
        SysRoleEntity role = new SysRoleEntity();
        BeanUtils.copyProperties(roleAddVo, role);
        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
            return R.error("新增角色'" + role.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
            return R.error("新增角色'" + role.getRoleName() + "'失败，角色权限已存在");
        }
        boolean success = roleService.create(role);
        if (success) {
            return R.ok();
        }
        return R.error("添加失败");
    }

    @ApiOperation(value = "修改角色", notes = "根据ID修改角色信息")
    @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "Long", paramType = "path")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败，角色名称或权限已存在")})
    @PreAuthorize("@customSs.hasPermission('system:role:edit')")
    @PostMapping("/update/{id}")
    public R update(@PathVariable Long id, @ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) {
        role.setRoleId(id);
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
            return R.error("修改角色'" + role.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
            return R.error("修改角色'" + role.getRoleName() + "'失败，角色权限已存在");
        }
        boolean success = roleService.updateById(role);
        if (success) {
            return R.ok();
        }
        return R.error("修改失败");
    }

    @ApiOperation(value = "批量删除角色", notes = "根据ID批量删除角色")
    @ApiImplicitParam(name = "roleIds", value = "角色ID数组", required = true, dataType = "Long[]", paramType = "path")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败")})
    @PreAuthorize("@customSs.hasPermission('system:role:remove')")
    @DeleteMapping("/{roleIds}")
    public R delete(@PathVariable Long[] roleIds) {
        boolean success = roleService.delete(roleIds);
        if (success) {
            return R.ok();
        }
        return R.error("删除失败");
    }

    @ApiOperation(value = "获取所有角色", notes = "获取系统中所有角色列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class, responseContainer = "List")})
    @GetMapping("/list-all")
    public R listAll() {
        List<SysRoleEntity> list = roleService.list();
        return R.ok(list);
    }

    @ApiOperation(value = "分页获取角色列表", notes = "根据角色名称分页获取角色列表")
    @ApiImplicitParams({@ApiImplicitParam(name = "keyword", value = "搜索关键词", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页记录数", defaultValue = "5", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页码", defaultValue = "1", dataType = "Integer", paramType = "query")})
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class, responseContainer = "Page")})
    @GetMapping("/list-page")
    public R listPage(@RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) {
        Page<SysRoleEntity> rolePage = roleService.list(keyword, pageSize, pageNum);
        return R.ok(rolePage);
    }

    @ApiOperation(value = "修改角色状态", notes = "启用或禁用角色")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "status", value = "状态(0-正常,1-停用)", required = true, dataType = "Integer", paramType = "query")})
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")})
    @PreAuthorize("@customSs.hasPermission('system:role:edit')")
    @PostMapping("/update-status/{id}")
    public R updateStatus(@PathVariable Long id, @RequestParam(value = "status") Integer status) {
        SysRoleEntity role = new SysRoleEntity();
        role.setRoleId(id);
        role.setStatus(status);
        boolean success = roleService.updateById(role);
        if (success) {
            return R.ok();
        }
        return R.error("修改失败");
    }

    @ApiOperation(value = "分配菜单权限", notes = "为角色分配菜单权限")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "分配失败")})
    @PreAuthorize("@customSs.hasPermission('system:role:auth')")
    @PostMapping("/auth-role-menu")
    public R authRoleMenu(@ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) {
        boolean success = roleService.authRoleMenu(role);
        if (success) {
            return R.ok();
        }
        return R.error("分配失败");
    }

    /**
     * 根据角色编号获取详细信息
     */
    @ApiOperation(value = "获取角色详情", notes = "根据角色ID获取角色详细信息")
    @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "path")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class)})
    @GetMapping(value = "/{roleId}")
    public R getInfo(@PathVariable Long roleId) {
        roleService.checkRoleDataScope(roleId);
        return R.ok(roleService.getById(roleId));
    }

    /**
     * 获取对应角色部门树列表
     */
    @ApiOperation(value = "获取角色部门树列表", notes = "获取角色关联的部门树结构")
    @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "path")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)})
    @GetMapping(value = "/deptTree/{roleId}")
    public R deptTree(@PathVariable("roleId") Long roleId) {
        Map<String, Object> resultMap = new HashMap<>(8);
        resultMap.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
        resultMap.put("depts", deptService.selectDeptTreeList(new SysDeptEntity()));
        return R.ok(resultMap);
    }

    /**
     * 修改保存数据权限
     */
    @ApiOperation(value = "保存数据权限", notes = "修改角色的数据权限范围")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)})
    @Log(title = "角色管理-保存数据权限", businessType = BusinessType.UPDATE)
    @PostMapping("/dataScope")
    public R dataScope(@ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        return R.ok(roleService.authDataScope(role));
    }

    /**
     * 查询已分配用户角色列表
     */
    @ApiOperation(value = "查询已分配用户角色列表", notes = "获取已经分配给指定角色的用户列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = RoleUserResultVo.class, responseContainer = "Page")})
    @PreAuthorize("@customSs.hasPermission('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public R allocatedList(SysUserQueryVo user) {
        IPage<RoleUserResultVo> list = userService.selectAllocatedList(user);
        return R.ok(list);
    }

    /**
     * 查询未分配用户角色列表
     */
    @ApiOperation(value = "查询未分配用户角色列表", notes = "获取尚未分配给指定角色的用户列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = RoleUserResultVo.class, responseContainer = "Page")})
    @PreAuthorize("@customSs.hasPermission('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public R unallocatedList(SysUserQueryVo user) {
        return R.ok(userService.selectUnallocatedList(user));
    }

    /**
     * 取消授权用户
     */
    @ApiOperation(value = "取消授权用户", notes = "取消指定用户的角色授权")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)})
    @PreAuthorize("@customSs.hasPermission('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancel")
    public R cancelAuthUser(@ApiParam(value = "用户角色关系", required = true) @RequestBody SysUserRoleEntity userRole) {
        return R.ok(roleService.deleteAuthUser(userRole));
    }

    /**
     * 批量取消授权用户
     */
    @ApiOperation(value = "批量取消授权用户", notes = "批量取消多个用户的角色授权")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "userIds", value = "用户ID数组", required = true, dataType = "String[]", paramType = "query")})
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)})
    @PreAuthorize("@customSs.hasPermission('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancelAll")
    public R cancelAuthUserAll(Long roleId, String[] userIds) {
        return R.ok(roleService.deleteAuthUsers(roleId, userIds));
    }

    /**
     * 批量选择用户授权
     */
    @ApiOperation(value = "批量选择用户授权", notes = "为角色批量添加用户授权")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "userIds", value = "用户ID数组", required = true, dataType = "String[]", paramType = "query")})
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)})
    @PreAuthorize("@customSs.hasPermission('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/selectAll")
    public R selectAuthUserAll(Long roleId, String[] userIds) {
        roleService.checkRoleDataScope(roleId);
        return R.ok(roleService.insertAuthUsers(roleId, userIds));
    }
}
