package com.microservices.system.controller;

import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.core.web.page.TableDataInfo;
import com.microservices.common.log.annotation.Log;
import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.InnerAuth;
import com.microservices.common.security.annotation.Logical;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.system.api.domain.SysUserDeptRole;
import com.microservices.system.domain.dto.GitLinkUserDeptRoleByDeptInput;
import com.microservices.system.domain.dto.SysUserDeptRoleByDeptInput;
import com.microservices.system.domain.vo.GitLinkUserSearchVo;
import com.microservices.system.service.ISysUserDeptRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 用户与组织及组织内角色关联Controller
 *
 * @author otto
 * @date 2023-04-12
 */
@Api(tags = "用户与组织及组织对应角色的关联操作")
@RestController
@RequestMapping("/SysUserDeptRole")
public class SysUserDeptRoleController extends BaseController {
    @Autowired
    private ISysUserDeptRoleService sysUserDeptRoleService;

    // region 以组织为主进行操作

    /**
     * 初始化会员在专区权限
     */
    @PutMapping("/initMemberRole")
    @ApiOperation("初始化会员在专区权限")
    public AjaxResult initMember() {
        sysUserDeptRoleService.initMemberRole();
        return success();
    }

    /**
     * 查询GitLink用户列表
     */
    @GetMapping("/dept/{currentDeptId}/gitlinkUserList")
    @ApiOperation("获取Gitlink用户列表")
    public GenericsTableDataInfo<JSONObject> gitlinkUserList(@PathVariable Long currentDeptId, GitLinkUserSearchVo gitLinkUserSearchVo) {
        return sysUserDeptRoleService.selectGitlinkUserList(currentDeptId, gitLinkUserSearchVo);
    }

    /**
     * 查询组织下用户及用户角色列表
     */
    @RequiresPermissions(value = {"system:SysUserDeptRole:list", "pms:pmsEnterprise:manageMember", "pms:pmsEnterprise:showMember"}, logical = Logical.OR)
    @GetMapping("/dept/{currentDeptId}/list")
    @ApiOperation("查询组织下用户及用户角色列表")
    public GenericsTableDataInfo<SysUserDeptRole> listByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                                             @ApiParam(name = "userName", value = "搜索条件-用户名") String userName,
                                                             @ApiParam(name = "nickName", value = "搜索条件-用户名称") String nickName,
                                                             @ApiParam(name = "roleId", value = "搜索条件-角色Id") String roleId) {
        return sysUserDeptRoleService.selectSysUserDeptRoleListByDept(currentDeptId, userName, nickName, roleId);
    }

    /**
     * 内部接口-模糊查询组织下身份列表
     */
    @InnerAuth
    @GetMapping("/dept/{currentDeptId}/searchList")
    @ApiOperation("模糊查询组织下身份列表")
    public R<GenericsTableDataInfo<SysUserDeptRole>> searchUserIdentifierListByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                                                                    @ApiParam(name = "search", value = "模糊搜索") String search,
                                                                                    @ApiParam(name = "pageNum", value = "当前记录起始索引") Integer pageNum,
                                                                                    @ApiParam(name = "pageSize", value = "每页显示记录数") Integer pageSize) {
        startPage();
        List<SysUserDeptRole> list = sysUserDeptRoleService.selectSysUserDeptRoleListByDept(currentDeptId, search);
        return R.ok(getGenericsDataTable(list));
    }

    /**
     * 内部接口-组织下新增用户身份
     */
    @InnerAuth
    @Log(title = "内部接口-组织下新增用户身份", businessType = BusinessType.INSERT)
    @PostMapping("/dept/{currentDeptId}/user/{userId}/role/{roleKey}")
    @ApiOperation(value = "组织下新增用户身份", hidden = true)
    public R<Boolean> addUserIdentify(@PathVariable("currentDeptId") Long currentDeptId, @PathVariable("userId") Long userId, @PathVariable("roleKey") String roleKey) {
        return R.ok(sysUserDeptRoleService.insertSysUserDeptRole(currentDeptId, userId, roleKey));

    }

    /**
     * 内部接口-根据部门Id和用户Id获取所有状态的用户身份
     *
     * @param deptId 组织Id
     * @param userId 用户Id
     * @return 用户身份
     */
    @InnerAuth
    @GetMapping("/dept/{deptId}/user/{userId}/allStatus")
    public R<SysUserDeptRole> getAllStatusUserIdentityByDeptIdAndUserId(
            @PathVariable("deptId") Long deptId,
            @PathVariable("userId") Long userId) {
        return R.ok(sysUserDeptRoleService.getAllStatusUserIdentityByDeptIdAndUserId(deptId, userId));
    }

    /**
     * 内部接口-组织下删除用户身份
     */
    @InnerAuth
    @Log(title = "内部接口-组织下删除用户身份", businessType = BusinessType.DELETE)
    @DeleteMapping("/dept/{currentDeptId}/user/{userId}/role/{roleKey}")
    @ApiOperation(value = "组织下删除用户身份", hidden = true)
    public R delete(@PathVariable("currentDeptId") Long currentDeptId, @PathVariable("userId") Long userId, @PathVariable("roleKey") String roleKey) {
        return R.ok(sysUserDeptRoleService.deleteSysUserDeptRole(currentDeptId, userId, roleKey));

    }

    /**
     * 组织下批量新增用户及用户角色
     */
    @RequiresPermissions(value = {"system:SysUserDeptRole:add", "pms:pmsEnterprise:manageMember"}, logical = Logical.OR)
    @Log(title = "组织下批量新增用户及用户角色", businessType = BusinessType.INSERT)
    @PostMapping("/dept/{currentDeptId}")
    @ApiOperation("组织下批量新增用户及用户角色")
    public AjaxResult addByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                @ApiParam(name = "sysUserDeptRoleByDeptInputs", value = "新增关联列表", required = true) @RequestBody SysUserDeptRoleByDeptInput[] sysUserDeptRoleByDeptInputs) {
        return toAjax(sysUserDeptRoleService.insertSysUserDeptRoleListByDept(currentDeptId, sysUserDeptRoleByDeptInputs));
    }

    /**
     * 组织下批量新增GitLink用户及用户角色
     */
    @RequiresPermissions(value = {"system:SysUserDeptRole:addGitLinkUser", "pms:pmsEnterprise:manageMember"}, logical = Logical.OR)
    @Log(title = "组织下批量新增GitLink用户及用户角色", businessType = BusinessType.INSERT)
    @PostMapping("/dept/{currentDeptId}/GitLinkUser")
    @ApiOperation("组织下批量新增GitLink用户及用户角色")
    public AjaxResult addGitLinkUserByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                           @ApiParam(name = "sysUserDeptRoleByDeptInputs", value = "新增关联列表", required = true)
                                           @Validated @RequestBody GitLinkUserDeptRoleByDeptInput[] gitLinkUserDeptRoleByDeptInputs) {
        return toAjax(sysUserDeptRoleService.insertGitLinkUserDeptRoleListByDept(currentDeptId, gitLinkUserDeptRoleByDeptInputs));
    }


    /**
     * 获取当前登录用户身份列表
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    @ApiOperation("获取当前登录用户身份列表")
    public TableDataInfo getInfo() {
        List<SysUserDeptRole> sysUserDeptRoleList = sysUserDeptRoleService.selectCurrentSysUserDeptRoleList();
        return getDataTable(sysUserDeptRoleList);
    }

    /**
     * 组织下批量修改用户与角色关联
     */
    @RequiresPermissions(value = {"system:SysUserDeptRole:edit", "pms:pmsEnterprise:manageMember"}, logical = Logical.OR)
    @Log(title = "组织下批量修改用户与角色关联", businessType = BusinessType.UPDATE)
    @PutMapping("/dept/{currentDeptId}")
    @ApiOperation("组织下批量修改用户与角色关联")
    public AjaxResult editByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                 @ApiParam(name = "sysUserDeptRoleByDeptInputs", value = "修改关联列表") @RequestBody SysUserDeptRoleByDeptInput[] sysUserDeptRoleByDeptInputs) {
        return toAjax(sysUserDeptRoleService.updateSysUserDeptRoleByDept(currentDeptId, sysUserDeptRoleByDeptInputs));
    }

    /**
     * 删除组织下用户
     */
    @RequiresPermissions(value = {"system:SysUserDeptRole:remove", "pms:pmsEnterprise:manageMember"}, logical = Logical.OR)
    @Log(title = "删除组织下用户", businessType = BusinessType.DELETE)
    @DeleteMapping("/dept/{currentDeptId}/users/{userIds}")
    @ApiOperation("删除组织下用户")
    public AjaxResult removeByDept(@ApiParam(name = "currentDeptId", value = "组织Id", required = true) @PathVariable("currentDeptId") Long currentDeptId,
                                   @ApiParam(name = "userIds", value = "用户Id列表") @PathVariable("userIds") Long[] userIds) {
        return toAjax(sysUserDeptRoleService.deleteSysUserDeptRoleByDeptIdAndUserIds(currentDeptId, userIds));
    }

    //endregion

    // region 以用户为主进行操作

    /**
     * 查询用户下组织及组织对应角色列表
     */
    @GetMapping("/user/{userId}/list")
    @ApiOperation("查询用户下身份列表")
    public TableDataInfo listByUser(@ApiParam(name = "userId", value = "用户Id", required = true) @PathVariable("userId") Long userId,
                                    @ApiParam(name = "isContainMember", value = "是否包含会员") Boolean isContainMember,
                                    @ApiParam(name = "deptName", value = "搜索条件-组织名") String deptName,
                                    @ApiParam(name = "roleName", value = "搜索条件-角色名") String roleName) {
        List<SysUserDeptRole> list = sysUserDeptRoleService.selectSysUserDeptRoleListByUser(userId, isContainMember, deptName, roleName);
        return getDataTable(list);
    }

    /**
     * 特色专区查询用户下组织及组织对应角色列表
     */
    @GetMapping("/zone/user/{userId}/list")
    @ApiOperation("特色专区查询用户下身份列表")
    public TableDataInfo zoneUserIdentityListByUser(@ApiParam(name = "userId", value = "用户Id", required = true) @PathVariable("userId") Long userId,
                                                    @ApiParam(name = "isContainMember", value = "是否包含会员") Boolean isContainMember,
                                                    @ApiParam(name = "deptName", value = "搜索条件-组织名") String deptName,
                                                    @ApiParam(name = "roleName", value = "搜索条件-角色名") String roleName) {
        List<SysUserDeptRole> list = sysUserDeptRoleService.selectZoneUserIdentityListByUser(userId, isContainMember, deptName, roleName);
        return getDataTable(list);
    }

    /**
     * 通过用户名查询用户下组织及组织对应角色列表
     */
    @ApiOperation(value = "通过用户名查询用户下组织及组织对应角色列表", hidden = true)
    @InnerAuth
    @GetMapping("/userByUserName/{userName}/list")
    public R<List<SysUserDeptRole>> getSysUserDeptRoleListByUserName(@PathVariable("userName") String userName) {
        List<SysUserDeptRole> list = sysUserDeptRoleService.selectSysUserDeptRoleListByUserName(userName);
        return R.ok(list);
    }

    /**
     * 通过组织Id查询组织下用户身份列表
     */
    @ApiOperation(value = "通过组织Id查询组织下用户身份列表", hidden = true)
    @InnerAuth
    @GetMapping("/userByDeptId/{currentDeptId}/list")
    public R<List<SysUserDeptRole>> getSysUserDeptRoleListByDeptId(@PathVariable("currentDeptId") Long currentDeptId) {
        List<SysUserDeptRole> list = sysUserDeptRoleService.selectSysUserDeptRoleListByDeptId(currentDeptId);
        return R.ok(list);
    }

    /**
     * 通过用户名查询用户下第一个身份
     */
    @ApiOperation(value = "通过用户名查询用户下第一个身份", hidden = true)
    @InnerAuth
    @GetMapping("/getFirstUserIdentity/{userName}")
    public R<SysUserDeptRole> getFirstUserIdentity(@PathVariable("userName") String userName) {
        SysUserDeptRole userIdentity = sysUserDeptRoleService.getFirstSysUserDeptRoleByUserName(userName);
        return R.ok(userIdentity);
    }

    // endregion

    /**
     * 检查用户是否在指定部门下具有指定角色
     *
     * @param currentDeptId 组织id
     * @param userId 用户id
     * @param roleKey 角色标识
     * @return 用户是否在指定部门下具有指定角色 是true 否false
     */
    @ApiOperation(value = "检查用户是否在指定部门下具有指定角色", hidden = true)
    @InnerAuth
    @GetMapping("/checkUserInDeptHasRole")
    public R<Boolean> checkUserInDeptHasRole(@ApiParam(name = "currentDeptId", value = "组织id", required = true) Long currentDeptId,
                                             @ApiParam(name="userId", value = "用户id", required = true) Long userId,
                                             @ApiParam(name="roleKey", value = "角色权限字符串", required = true) String roleKey) {
        Boolean userInDeptHasRole = sysUserDeptRoleService.checkUserInDeptHasRole(currentDeptId, userId, roleKey);
        return R.ok(userInDeptHasRole);
    }

    /**
     * 检查用户是否在指定部门下具有指定菜单权限
     *
     * @param currentDeptId 组织id
     * @param userId        用户id
     * @param perms         菜单权限
     * @return 用户是否在指定部门下具有菜单权限 是true 否false
     */
    @ApiOperation(value = "检查用户是否在指定部门下具有指定菜单权限", hidden = true)
    @InnerAuth
    @GetMapping("/checkUserInDeptHasPerms")
    public R<Boolean> checkUserInDeptHasPerms(@ApiParam(name = "currentDeptId", value = "组织id", required = true) Long currentDeptId,
                                              @ApiParam(name = "userId", value = "用户id", required = true) Long userId,
                                              @ApiParam(name = "perms", value = "菜单权限", required = true) String perms) {
        Boolean userInDeptHasRole = sysUserDeptRoleService.checkUserInDeptHasPerms(currentDeptId, userId, perms);
        return R.ok(userInDeptHasRole);
    }

    /**
     * 检查用户是否在指定部门下
     *
     * @param currentDeptId 组织id
     * @param userId        用户id
     * @return 用户是否在指定部门下 是true 否false
     */
    @ApiOperation(value = "用户是否在指定部门下", hidden = true)
    @InnerAuth
    @GetMapping("/checkUserInDept")
    public R<Boolean> checkUserInDept(@ApiParam(name = "currentDeptId", value = "组织id", required = true) Long currentDeptId,
                                      @ApiParam(name = "userId", value = "用户id", required = true) Long userId) {
        Boolean userInDept = sysUserDeptRoleService.checkUserInDept(currentDeptId, userId);
        return R.ok(userInDept);
    }
}
