package com.fdkanfang.web.backend;

import com.fdkanfang.common.constant.MsgCode;
import com.fdkanfang.common.model.PageDto;
import com.fdkanfang.common.util.PasswordUtils;
import com.fdkanfang.domain.backend.RoleEntity;
import com.fdkanfang.domain.dto.UserDto;
import com.fdkanfang.common.util.R;
import com.fdkanfang.domain.backend.UserEntity;
import com.fdkanfang.domain.response.UserResponse;
import com.fdkanfang.service.backend.RoleService2;
import com.fdkanfang.service.backend.UserService2;
import com.fdkanfang.web.aop.WebControllerLog;
import com.fdkanfang.web.backend.utils.UserUtils;
import com.fdkanfang.web.shiro.JWTUtil;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * Created by owen on 2020/2/18 0018 12:17
 */
@Log4j2
@Api(tags = "用户管理")
@RestController
@RequestMapping("manage/user")
@Transactional
public class UserController extends BaseController {

    @Autowired
    public UserService2 userService2;

    @Autowired
    public RoleService2 roleService2;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    public RedisTemplate<Object, Object> redisTemplate;


    private static String roleskey = "checkRole_";


    //    @RequiresRoles("admin")
    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @WebControllerLog(description = "用户管理-用户列表")
    @ApiOperation("分页获取用户列表")
    @PostMapping("list")
    public R list(@RequestBody PageDto param) {
        PageInfo<UserResponse> page = new PageInfo<>(userService2.findAllBySearchKey(param));
        return new R(2000, page);
    }

    /**
     * 暂时只有修改，没有新增(现在的新增是测试用的)
     */
    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("新增或修改用户信息")
    @PostMapping("save")
    public R save(@Valid @RequestBody UserDto param) {

        UserEntity user = null;
        if (param.getId() == null) {
            // 目前的需求，这个方法是没有新增用户的，这个新增只是那里开发测试用的
            user = new UserEntity();
            BeanUtils.copyProperties(param, user);
            param.setPassword("123456");
            user.setPassword(PasswordUtils.encrypt(param.getUserName(), param.getPassword(), PasswordUtils.getStaticSalt()));
            userService2.save(user);
        } else {
            user = userService2.findById(param.getId());
            if (user == null) {
                log.error("用户不存在： {}", param.getId());
                return new R(MsgCode.e_ADMIN_4001, MsgCode.msg_ADMIN_4001);
            }
            BeanUtils.copyProperties(param, user);
            user.setUpdateTime(new Date());
            userService2.update(user);
        }


        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("删除用户")
    @GetMapping("delete/{id}")
    public R delete(@PathVariable Long id) {

        // 管理员不能删除自己的账号
        Set<String> roles = userService2.findRoleByUserId(id);
        if (roles.contains("admin")) {
            log.error("管理员账户不能删除： {}", id);
            return new R(MsgCode.e_ADMIN_4101, MsgCode.msg_ADMIN_4101);
        }

        userService2.deleteById(id);


        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("批量删除用户")
    @GetMapping("delete/all/{ids}")
    public R deleteAll(@PathVariable String ids) {

        // 管理员账户不能删除
        String[] split = ids.split(",");
        for (String s : split) {
            Set<String> roles = userService2.findRoleByUserId(Long.valueOf(s));
            if (roles.contains("admin")) {
                log.info("管理员账户不能删除： {}", s);
                return new R(MsgCode.e_ADMIN_4101, MsgCode.msg_ADMIN_4101);
            }
        }

        userService2.deleteByIds(ids);
        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @ApiOperation("查询用户信息")
    @GetMapping("detail/{id}")
    public R detail(@PathVariable Long id) {
        UserEntity user = userService2.findById(id);
        return new R(2000, user);
    }

    @ApiOperation("修改密码")
    @PostMapping("updatePwd")
    public R updatePwd(@RequestParam String oldPassword, @RequestParam String password) {

        UserEntity user = userService2.findByUserName(JWTUtil.getUserName(getToken()));

        // 验证原密码
        Boolean isBoolean = PasswordUtils.decrypt(user.getPassword(), oldPassword, PasswordUtils.getStaticSalt());
        if (!isBoolean) {
            log.error("原始密码错误");
            return new R(5100, "原密码错误");
        }

        user.setPassword(PasswordUtils.encrypt(user.getUserName(), password, PasswordUtils.getStaticSalt()));
        userService2.update(user);
        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @ApiOperation("重置密码")
    @GetMapping("resetPass/{id}")
    public R resetPass(@PathVariable Long id) {
        UserEntity user = userService2.findById(id);
        user.setPassword(PasswordUtils.encrypt(user.getUserName(), "123456", PasswordUtils.getStaticSalt()));
        user.setUpdateTime(new Date());
        userService2.update(user);
        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("启用、停用账户")
    @GetMapping("setStatus/{id}/{status}")
    public R setStatus(@PathVariable Long id, @PathVariable Integer status) {

        UserEntity user = userService2.findById(id);
        if (user == null) {
            log.error("用户不存在： {}", id);
            return new R(MsgCode.e_COMMON_3002, MsgCode.msg_COMMON_3002);
        }

        // 管理员账号不能停用
        Set<String> roles = userService2.findRoleByUserId(id);
        if (roles.contains("admin")) {
            log.info("管理员账户不能停用： {}", id);
            return new R(MsgCode.e_ADMIN_4101, MsgCode.msg_ADMIN_4101);
        }

        user.setStatus(status);
        user.setUpdateTime(new Date());

        userService2.update(user);
        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }


    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("批量启用/停用账户")
    @GetMapping("setStatus/all/{ids}/{status}")
    public R setStatusAll(@PathVariable String ids, @PathVariable Integer status) {
        List<UserEntity> userList = userService2.findByIds(ids);

        if (userList == null) {
            log.error("参数有误或者用户不存在： {}", ids);
            return new R(MsgCode.e_COMMON_3001, MsgCode.msg_COMMON_3001);
        }

        // 管理员账户不能改自己的状态
        for (UserEntity user : userList) {
            user.setUpdateTime(new Date());
            user.setStatus(status);
            Set<String> roles = userService2.findRoleByUserId(user.getId());
            if (roles.contains("admin")) {
                log.info("管理员账户不能停用： {}", user.getId());
                return new R(MsgCode.e_ADMIN_4101, MsgCode.msg_ADMIN_4101);
            }

            userService2.update(user);
        }

        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

//    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("获取角色")
    @GetMapping("getRole")
    public R getRole() {
        List<RoleEntity> list = roleService2.findAll();
        return new R(2000, list);
    }


    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("查询用户权限")
    @GetMapping("find/auth/{id}")
    public R userAuth(@PathVariable Long id) {
        Set<Integer> roles = userService2.findRoleIdByUserId(id);
        return new R(2000, roles);
    }



    /**
     * 前端每一步都在验证，需要用redis
     */
    @ApiOperation("前端检查角色")
    @GetMapping("checkRole")
    public R checkRole() {
        // 获取用户角色
        UserEntity user  = userUtils.getUserByToken(getToken());
        Long userId = user.getId();

        String redisKey = roleskey + userId;

        Set<String> roles = (Set) redisTemplate.opsForValue().get(redisKey);
        if (roles == null) {
            log.info("redisRoles is null");
            roles = userService2.findRoleByUserId(userId);

            // 更新到 redis, 有效期60min
            redisTemplate.opsForValue().set(redisKey, roles, Long.parseLong("60"), TimeUnit.MINUTES);
        }

        return new R(2000, roles);
    }


    @RequiresRoles(value = {"admin"}, logical = Logical.OR)
    @ApiOperation("用户角色授权,roleId:用逗号隔开")
    @GetMapping("accredit/{id}")
    public R accredit(@PathVariable Long id, @RequestParam(name = "roleIds")  String roleIds) {

        // 先删除用户角色表，再添加，不然会出错；
        userService2.deleteUserRoleByUserId(id);

        // 删除redis role
        if(!redisTemplate.delete(roleskey + id)){
            log.warn("删除角色[{}]在redis中的缓存key=[{}]失败" , roleskey + id);
        }else{
            log.info("删除角色[{}]在redis中的缓存key=[{}]成功" , roleskey + id);
        }


        // 重新添加角色
        String[] split = StringUtils.split(roleIds, ",");
        for (String roleId : split) {
            userService2.saveUserRole(id, Long.valueOf(roleId));
        }

        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }


}
