package com.sunyard.ssp.modules.user.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sunyard.ssp.common.PageVo;
import com.sunyard.ssp.common.Result;
import com.sunyard.ssp.common.constant.ValidatorConstant;
import com.sunyard.ssp.modules.user.entity.ScRole;
import com.sunyard.ssp.modules.user.entity.ScRoleDepartment;
import com.sunyard.ssp.modules.user.entity.ScRolePermission;
import com.sunyard.ssp.modules.user.entity.ScUserRole;
import com.sunyard.ssp.modules.user.service.IScRoleDepartmentService;
import com.sunyard.ssp.modules.user.service.IScRolePermissionService;
import com.sunyard.ssp.modules.user.service.IScRoleService;
import com.sunyard.ssp.modules.user.service.IScUserRoleService;
import com.sunyard.ssp.modules.user.utils.validator.RoleValidator;
import com.sunyard.ssp.redis.RedisObjectOperation;
import com.sunyard.ssp.utils.PageUtil;
import com.sunyard.ssp.utils.ResultUtil;
import com.sunyard.ssp.vo.ScRoleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.DataBinder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author tsz
 * @since 2020-03-11
 */
@RestController
@Slf4j
@RequestMapping("/role")
@Transactional
public class ScRoleController {

    @Autowired
    IScRoleService roleService;

    @Autowired
    IScRolePermissionService rolePermissionService;

    @Autowired
    IScRoleDepartmentService roleDepartmentService;

    @Autowired
    IScUserRoleService userRoleService;

    @Autowired
    RoleValidator roleValidator;
    @Autowired
    private RedisObjectOperation redisObjectOperation;

    @InitBinder(ValidatorConstant.ROLE_BASE_NAME)
    public void initBainder(DataBinder binder){
        binder.replaceValidators(roleValidator);
    }

    @RequestMapping(value = "/getAllList",method = RequestMethod.GET)
    public Result<Object> roleGetAll(){

        List<ScRole> list = roleService.list();
        return new ResultUtil<Object>().setData(list);
    }

    @RequestMapping(value = "/getAllByPage",method = RequestMethod.GET)
    public Result<org.springframework.data.domain.Page<ScRoleVo>> getRoleByPage(@ModelAttribute PageVo page){

        org.springframework.data.domain.Page<ScRole> list = roleService.findAll(PageUtil.initPage(page));
        List<ScRoleVo> roleVos = new LinkedList<>();
        for(ScRole role : list.getContent()){
            // 角色拥有权限
            List<ScRolePermission> permissions = rolePermissionService.list(new QueryWrapper<ScRolePermission>().lambda()
                    .eq(ScRolePermission::getRoleId,role.getId()));
            // 角色拥有数据权限
            List<ScRoleDepartment> departments = roleDepartmentService.list(new QueryWrapper<ScRoleDepartment>().lambda()
                    .eq(ScRoleDepartment::getRoleId,role.getId()));

            roleVos.add(new ScRoleVo(role, permissions, departments));
        }

        return new ResultUtil<org.springframework.data.domain.Page<ScRoleVo>>()
                .setData(new PageImpl<ScRoleVo>(roleVos, PageUtil.initPage(page), list.getTotalElements()));
    }

    @RequestMapping(value = "/getDefault",method = RequestMethod.GET)
    public Result<Object> getDefault(){

        List<ScRole> list = roleService.list(new QueryWrapper<ScRole>().lambda().eq(ScRole::getDefaultRole, true));
        return new ResultUtil<Object>().setData(list);
    }

    @RequestMapping(value = "/setDefault",method = RequestMethod.POST)
    public Result<Object> setDefault(@RequestParam String id,
                                     @RequestParam Boolean isDefault){

        ScRole role = roleService.getById(id);
        if(role==null){
            return new ResultUtil<Object>().setErrorMsg("角色不存在");
        }
        role.setDefaultRole(isDefault);
        roleService.updateById(role);
        return new ResultUtil<Object>().setSuccessMsg("设置成功");
    }

    @RequestMapping(value = "/editRolePerm",method = RequestMethod.POST)
    public Result<Object> editRolePerm(@RequestParam Long roleId,
                                       @RequestParam(required = false) Long[] permIds){
        ScRole role = roleService.getById(roleId);
        //删除其关联权限
        rolePermissionService.remove(new QueryWrapper<ScRolePermission>().lambda().eq(ScRolePermission::getRoleId,roleId));
        //分配新权限
        for(Long permId : permIds){
            ScRolePermission rolePermission = new ScRolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permId);
            rolePermissionService.save(rolePermission);
        }
        //手动批量删除缓存
        Set<String> keysUser = redisObjectOperation.keys("user:" + "*");
        redisObjectOperation.delete(keysUser);
        Set<String> keysUserRole = redisObjectOperation.keys("userRole:" + "*");
        redisObjectOperation.delete(keysUserRole);
        Set<String> keysUserPerm = redisObjectOperation.keys("userPermission:" + "*");
        redisObjectOperation.delete(keysUserPerm);
        Set<String> keysUserMenu = redisObjectOperation.keys("permission::userMenuList:*");
        redisObjectOperation.delete(keysUserMenu);
        return new ResultUtil<Object>().setData(null);
    }

    @RequestMapping(value = "/editRoleDep",method = RequestMethod.POST)
    public Result<Object> editRoleDep(@RequestParam Long roleId,
                                      @RequestParam Integer dataType,
                                      @RequestParam(required = false) Long[] depIds){

        ScRole r = roleService.getById(roleId);
        r.setDataType(dataType);
        roleService.updateById(r);
        // 删除其关联数据权限
        roleDepartmentService.remove(new QueryWrapper<ScRoleDepartment>().lambda().eq(ScRoleDepartment::getRoleId, roleId));
        // 分配新数据权限
        for(Long depId : depIds){
            ScRoleDepartment roleDepartment = new ScRoleDepartment();
            roleDepartment.setRoleId(roleId);
            roleDepartment.setDepartmentId(depId);
            roleDepartmentService.save(roleDepartment);
        }
        // 手动删除相关缓存
        Set<String> keys = redisObjectOperation.keys("department:" + "*");
        redisObjectOperation.delete(keys);
        Set<String> keysUserRole = redisObjectOperation.keys("userRole:" + "*");
        redisObjectOperation.delete(keysUserRole);

        return new ResultUtil<Object>().setData(null);
    }

    @RequestMapping(value = "/save",method = RequestMethod.POST)
    public Result<ScRole> save(@ModelAttribute(ValidatorConstant.ROLE_BASE_NAME)  @Validated ScRole role){

        if(roleService.save(role)) {
            return new ResultUtil<ScRole>().setData(role);
        }
        return new ResultUtil<ScRole>().setErrorMsg("save error");
    }

    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    public Result<ScRole> edit(@ModelAttribute(ValidatorConstant.ROLE_BASE_NAME)  @Validated ScRole entity){

        ScRole oldRole = roleService.getById(entity.getId());

        roleService.updateById(entity);
        //手动批量删除缓存
        Set<String> keysUser = redisObjectOperation.keys("user:" + "*");
        redisObjectOperation.delete(keysUser);
        Set<String> keysUserRole = redisObjectOperation.keys("userRole:" + "*");
        redisObjectOperation.delete(keysUserRole);
        return new ResultUtil<ScRole>().setData(entity);
    }

    @RequestMapping(value = "/delAllByIds/{ids}",method = RequestMethod.DELETE)
    public Result<Object> delByIds(@PathVariable String[] ids){

        for(String id:ids){
            List<ScUserRole> list = userRoleService.list(new QueryWrapper<ScUserRole>().lambda().eq(ScUserRole::getRoleId, id));
            if(list!=null&&list.size()>0){
                return new ResultUtil<Object>().setErrorMsg("删除失败，包含正被用户使用关联的角色");
            }
        }
        for(String id:ids){
            roleService.removeById(id);
            //删除关联菜单权限
            rolePermissionService.remove(new QueryWrapper<ScRolePermission>().lambda().eq(ScRolePermission::getRoleId,id));
            //删除关联数据权限
            roleDepartmentService.remove(new QueryWrapper<ScRoleDepartment>().lambda().eq(ScRoleDepartment::getRoleId,id));
        }
        return new ResultUtil<Object>().setSuccessMsg("批量通过id删除数据成功");
    }
}
