package com.jiayue.ssi.controller;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.crypto.SmUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiayue.ssi.annotation.AgainVerify;
import com.jiayue.ssi.annotation.OperateLog;
import com.jiayue.ssi.annotation.PreventReplay;
import com.jiayue.ssi.backenum.ApproveStatusEnum;
import com.jiayue.ssi.backenum.AuditType;
import com.jiayue.ssi.backenum.BusinessType;
import com.jiayue.ssi.config.SendMailUtil;
import com.jiayue.ssi.constant.CacheConstants;
import com.jiayue.ssi.constant.CustomException;
import com.jiayue.ssi.entity.*;
import com.jiayue.ssi.service.*;
import com.jiayue.ssi.service.impl.SysPermissionService;
import com.jiayue.ssi.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 用户信息接口
 *
 * @author xsl
 * @since 2023/03/13
 */
@RestController
@RequestMapping("/sysUserController")
@Slf4j
public class SysUserController {
    @Autowired
    SysUserService sysUserService;
    @Autowired
    SendMailUtil sendMailUtil;
    @Autowired
    SysPermissionService sysPermissionService;
    @Autowired
    SysUserRoleService sysUserRoleService;
    @Autowired
    SysApproveService sysApproveService;
    @Autowired
    SysRoleService sysRoleService;
    @Autowired
    SysPolicyService sysPolicyService;

    /**
     * 获取用户分页信息
     *
     * @return 用户信息
     */
    @GetMapping(value = "/getAll")
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @PreventReplay
    public ResponseVO getAll(String currentPage, String pageSize, String username, String phonenumber,
                             String status) throws CustomException {
        try {
            Integer cp;
            if (StringUtils.isNotEmpty(currentPage)) {
                if (NumberUtil.isInteger(currentPage)){
                    cp = Integer.parseInt(currentPage);
                }
                else{
                    return ResponseVO.fail("currentPage不是整数！");
                }
            }
            else{
                return ResponseVO.fail("currentPage不能是空！");
            }

            Integer ps;
            if (StringUtils.isNotEmpty(pageSize)) {
                if (NumberUtil.isInteger(pageSize)){
                    ps = Integer.parseInt(pageSize);
                }
                else{
                    return ResponseVO.fail("pageSize不是整数！");
                }
            }
            else{
                return ResponseVO.fail("pageSize不能是空！");
            }

            if (StringUtils.isNotEmpty(username)) {
                if (username.length() > 20) {
                    return ResponseVO.fail("用户账号长度不能超过20个字符！");
                }
            }
            if (StringUtils.isNotEmpty(phonenumber)) {
                if (phonenumber.length() > 11) {
                    return ResponseVO.fail("手机号码长度不能超过11个字符！");
                }
            }
            QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
            if (StringUtils.isNotEmpty(username)) {
                wrapper.eq("username", username);
            }
            if (StringUtils.isNotEmpty(phonenumber)) {
                wrapper.eq("AES_DECRYPT(UNHEX(phonenumber), '" + new String(AesUtils.key) + "')", phonenumber);
            }
            if (StringUtils.isNotEmpty(status)) {
                wrapper.eq("status", status);
            }

            SysRole sysRole = sysRoleService.selectRoleListByUserId();
            if ("YWGL".equals(sysRole.getRoleKey())){
                // 业务管理员员
                wrapper.eq("usertype", "1");
            }

            Page<SysUser> result = sysUserService.page(new Page<>(cp, ps), wrapper);
            List<SysUser> records = result.getRecords();
            //遍历对象数组的方法
            records.forEach(
                    record -> {
                        record.setMailbox(AesUtils.decryptStr(record.getMailbox()));
                        record.setPhonenumber(AesUtils.decryptStr(record.getPhonenumber()));
                        record.setNickname(AesUtils.decryptStr(record.getNickname()));
                    }
            );
            return ResponseVO.success(result);
        } catch (Exception e) {
            throw new CustomException("获取所有用户异常", e);
        }
    }

    /**
     * 获取当前用户信息
     *
     * @return 用户信息
     */
    @GetMapping(value = "/getCurrentUser")
    public ResponseVO getCurrentUser() throws CustomException {
        try {
            SysUser sysUser = SecurityContextUtil.getSysUser();
            // 权限集合
            Set<String> permissions = sysPermissionService.getMenuPermission(sysUser.getId());
            Map<String, Object> map = new HashMap<>();
            sysUser.setMailbox(AesUtils.decryptStr(sysUser.getMailbox()));
            sysUser.setPhonenumber(AesUtils.decryptStr(sysUser.getPhonenumber()));
            sysUser.setNickname(AesUtils.decryptStr(sysUser.getNickname()));
            map.put("sysUser", sysUser);
            map.put("permissions", permissions);
            return ResponseVO.success(map);
        } catch (Exception e) {
            throw new CustomException("获取当前用户异常", e);
        }
    }

    /**
     * 新增用户
     */
    @PostMapping(value = "/addUser")
    @OperateLog(title = "用户管理", businessType = BusinessType.INSERT, auditType = AuditType.SYS)
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @PreventReplay
    public ResponseVO addUser(@RequestBody SysUser user) throws CustomException {
        try {
            if (StringUtils.isEmpty(user.getUsername())) {
                return ResponseVO.fail("用户账号不能为空!");
            } else if (sysUserService.queryUserName(user.getUsername()) != null) {
                return ResponseVO.fail(user.getUsername() + "账号已存在！");
            } else if (user.getUsername().length() < 5 || user.getUsername().length() > 20) {
                return ResponseVO.fail(user.getUsername() + "用户账号长度必须介于5和20之间！");
            }

            if (StringUtils.isEmpty(user.getPhonenumber())) {
                return ResponseVO.fail("手机号码不能为空！");
            } else if (!Validator.isMobile(user.getPhonenumber())) {
                return ResponseVO.fail("请输入正确的手机号码！");
            }
            // 加密手机号
            user.setPhonenumber(AesUtils.encryptHex(user.getPhonenumber()).toUpperCase());

            if (StringUtils.isEmpty(user.getNickname())) {
                return ResponseVO.fail("姓名不能为空！");
            } else if (user.getNickname().length() > 30) {
                return ResponseVO.fail("姓名长度不能超过30个字符！");
            }
            // 加密姓名
            user.setNickname(AesUtils.encryptHex(user.getNickname()).toUpperCase());

            if (StringUtils.isEmpty(user.getMailbox())) {
                return ResponseVO.fail("邮箱不能为空!");
            } else if (!Validator.isEmail(user.getMailbox())) {
                return ResponseVO.fail("请输入正确的邮箱地址！");
            } else if (user.getMailbox().length() > 50) {
                return ResponseVO.fail("邮箱长度不能超过50个字符！");
            } else if (sysUserService.queryMailBox(user.getMailbox()) != null) {
                return ResponseVO.fail(user.getMailbox() + "邮箱已存在！");
            }
            // 加密邮箱
            user.setMailbox(AesUtils.encryptHex(user.getMailbox()).toUpperCase());

//        // 生成8位初始密码
//        String randomPwd = RandomPwd.getRandomPwd(8);
//        user.setPassword(SmUtil.sm3(randomPwd).toUpperCase());
//        user.setErrNum(0);
//        user.setLockTime(0L);
            boolean bo = sysUserService.save(user);
            if (bo) {
                return ResponseVO.success("添加用户信息成功");
            } else {
                log.error("添加用户信息失败");
                return ResponseVO.fail("添加用户信息失败");
            }
        } catch (Exception e) {
            throw new CustomException("添加用户信息异常", e);
        }
    }

    /**
     * 更新用户
     *
     * @param user 参数
     * @return 执行结果
     */
    @PostMapping(value = "/updateUser")
    @OperateLog(title = "用户管理", businessType = BusinessType.UPDATE, auditType = AuditType.SYS)
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @PreventReplay
    public ResponseVO updateUser(@RequestBody SysUser user) throws CustomException {
        try {
            SysUser existUser = sysUserService.getById(user.getId());
            if (existUser == null) {
                return ResponseVO.fail("id为空不能修改!");
            }

            // 获取审批表是否存在此操作
            QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
            // 条件：待审批
            wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
            // 条件：删除操作
            wrapper.eq("master_id", user.getId());
            // 条件：实体名
            wrapper.eq("entity_name", "SysUser");
            List<SysApprove> list = sysApproveService.list(wrapper);
            if (list.size() > 0) {
                return ResponseVO.fail("此记录存在未审批的操作,不能进行修改！");
            }

            if (StringUtils.isEmpty(user.getUsername())) {
                return ResponseVO.fail("用户账号不能为空!");
            } else if (user.getUsername().length() < 5 || user.getUsername().length() > 20) {
                return ResponseVO.fail(user.getUsername() + "用户账号长度必须介于5和20之间！");
            } else if (!existUser.getUsername().equals(user.getUsername())) {
                if (sysUserService.queryUserName(user.getUsername()) != null) {
                    return ResponseVO.fail(user.getUsername() + "账号已存在！");
                }
            }

            if (StringUtils.isEmpty(user.getMailbox())) {
                return ResponseVO.fail("邮箱不能为空!");
            } else if (!Validator.isEmail(user.getMailbox())) {
                return ResponseVO.fail("请输入正确的邮箱地址！");
            } else if (user.getMailbox().length() > 50) {
                return ResponseVO.fail("邮箱长度不能超过50个字符！");
            } else if (!existUser.getMailbox().equals(user.getMailbox())) {
                if (sysUserService.queryMailBox(user.getMailbox()) != null) {
                    return ResponseVO.fail(user.getMailbox() + "邮箱已存在！");
                }
            }
            // 加密邮箱
            user.setMailbox(AesUtils.encryptHex(user.getMailbox()).toUpperCase());

            if (StringUtils.isEmpty(user.getPhonenumber())) {
                return ResponseVO.fail("手机号码不能为空！");
            } else if (!Validator.isMobile(user.getPhonenumber())) {
                return ResponseVO.fail("请输入正确的手机号码！");
            }
            // 加密手机号
            user.setPhonenumber(AesUtils.encryptHex(user.getPhonenumber()).toUpperCase());

            if (StringUtils.isEmpty(user.getNickname())) {
                return ResponseVO.fail("姓名不能为空！");
            } else if (user.getNickname().length() > 30) {
                return ResponseVO.fail("姓名长度不能超过30个字符！");
            }
            // 加密姓名
            user.setNickname(AesUtils.encryptHex(user.getNickname()).toUpperCase());


            if ("0".equals(user.getStatus())) {
                user.setErrNum(0);
                user.setLockTime(0L);
            }

            if (user.getExpDate()==null) {
                user.setExpDate(null);
            }

            boolean bo = sysUserService.updateUser(user);
            if (bo) {
                return ResponseVO.success("修改用户信息成功");
            } else {
                log.error("修改用户信息失败");
                return ResponseVO.fail("修改用户信息失败");
            }
        } catch (Exception e) {
            throw new CustomException("修改用户信息异常", e);
        }
    }

    /**
     * 初始密码发送邮箱
     */
    @PostMapping(value = "/resetPassword")
    @OperateLog(title = "用户管理", businessType = BusinessType.OTHER, auditType = AuditType.SYS)
    @PreAuthorize("@ss.hasPermi('system:user:send')")
    @PreventReplay
    public ResponseVO resetPassword(String id) {
        if (StringUtils.isEmpty(id)) {
            return ResponseVO.fail("重置密码缺失id!");
        }
        // 获取审批表是否存在此操作
        QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
        // 条件：待审批
        wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
        // 条件：删除操作
        wrapper.eq("master_id", id);
        // 条件：实体名
        wrapper.eq("entity_name", "SysUser");
        List<SysApprove> list = sysApproveService.list(wrapper);
        if (list.size() > 0) {
            return ResponseVO.fail("此记录存在未审批的操作,不能进行修改！");
        }
        // id获取用户
        SysUser sysUser = sysUserService.getById(id);
        if (sysUser == null) {
            return ResponseVO.fail("重置密码失败！");
        }
        // 生成8位初始密码
        String randomPwd = RandomPwd.getRandomPwd(8);
        boolean bo = sysUserService.resetPassword(Integer.parseInt(id), SmUtil.sm3(randomPwd).toUpperCase());
        if (!bo) {
            return ResponseVO.fail("密码生成失败！");
        }
        try {
            String[] mailArray = {AesUtils.decryptStr(sysUser.getMailbox())};
            sendMailUtil.executeSendMail(mailArray, "系统登录密码", "密码：" + randomPwd);
        } catch (Exception e) {
            log.error("用户名："+sysUser.getUsername()+",邮箱验证码发送失败！",e);
            return ResponseVO.fail("发送邮箱失败");
        }
        return ResponseVO.success();
    }

    /**
     * 删除用户信息
     */
    @PostMapping(value = "/delUser")
    @AgainVerify
    @OperateLog(title = "用户管理", businessType = BusinessType.DELETE, auditType = AuditType.SYS)
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @PreventReplay
    public ResponseVO delete(String id) throws CustomException {
        try {
            if (StringUtils.isEmpty(id)) {
                return ResponseVO.fail("id不能为空!");
            }
            // id获取用户
            SysUser sysUser = sysUserService.getById(id);
            if (sysUser == null) {
                return ResponseVO.fail("id为空不能删除用户！");
            }

            // 获取审批表是否存在此操作
            QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
            // 条件：待审批
            wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
            // 条件：删除操作
            wrapper.eq("master_id", id);
            // 条件：实体名
            wrapper.eq("entity_name", "SysUser");
            List<SysApprove> list = sysApproveService.list(wrapper);
            if (list.size() > 0) {
                return ResponseVO.fail("此记录存在未审批的操作,不能进行删除！");
            }

            boolean bo = sysUserService.removeUserById(sysUser);
            if (bo) {
                return ResponseVO.success("【删除用户】已进入审批，审批通过后实现真正删除！");
            } else {
                log.error("删除用户信息失败");
                return ResponseVO.fail("删除用户信息失败");
            }
        } catch (Exception e) {
            throw new CustomException("删除用户信息异常", e);
        }
    }

    /**
     * 修改密码
     */
    @PostMapping(value = "/updatePassword")
    @OperateLog(title = "用户管理", businessType = BusinessType.UPDATE, auditType = AuditType.SYS)
    @PreventReplay
    public ResponseVO updatePassword(String id, String oldPassword, String newPassword, String confirmPassword) throws CustomException {
        try {
            oldPassword = oldPassword.trim();
            newPassword = newPassword.trim();
            confirmPassword = confirmPassword.trim();

            if (StringUtils.isEmpty(id)) {
                return ResponseVO.fail("修改密码缺失id!");
            }
            // 获取审批表是否存在此操作
            QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
            // 条件：待审批
            wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
            // 条件：删除操作
            wrapper.eq("master_id", id);
            // 条件：实体名
            wrapper.eq("entity_name", "SysUser");
            List<SysApprove> list = sysApproveService.list(wrapper);
            if (list.size() > 0) {
                return ResponseVO.fail("此记录存在未审批的操作,不能进行修改！");
            }
            // id获取用户
            SysUser sysUser = sysUserService.getById(id);
            if (sysUser == null) {
                return ResponseVO.fail("找不到用户,修改密码失败！");
            }

            if (newPassword == null || newPassword.length() < 8 || newPassword.length() > 20) {
                // 返回密码长度问题
                return ResponseVO.fail("密码长度需要8~20位之间！");
            }

            if (StringUtils.isEmpty(oldPassword)) {
                return ResponseVO.fail("旧密码不能为空!");
            } else if (!sysUser.getPassword().equals(SmUtil.sm3(oldPassword).toUpperCase())) {
                return ResponseVO.fail("旧密码不正确！");
            }

            if (StringUtils.isEmpty(newPassword)) {
                return ResponseVO.fail("新密码不能为空!");
            } else if (StringUtils.isEmpty(confirmPassword)) {
                return ResponseVO.fail("确认密码不能为空！");
            } else if (!newPassword.equals(confirmPassword)) {
                return ResponseVO.fail("新密码两次输入的密码不一致！");
            }
            // 对新密码规则验证
            if (newPassword.contains(sysUser.getUsername())) {
                return ResponseVO.fail("密码不能含有账号！");
            }
            if (SmUtil.sm3(newPassword).toUpperCase().equals(sysUser.getPassword())) {
                return ResponseVO.fail("新密码不能与上次密码相同！");
            }

            SysPolicy sysPolicy = sysPolicyService.getOne(new QueryWrapper<>());
            String ruleInfo = PasswordRuleUtil.ruleRegx(sysPolicy.getPasswordRule(),newPassword);
            if (!"true".equals(ruleInfo)){
                return ResponseVO.fail(ruleInfo);
            }

            sysUser.setPassword(SmUtil.sm3(newPassword).toUpperCase());
            sysUser.setLastUpdatePwdTime(new Date());
            boolean bo = sysUserService.updateById(sysUser);
            if (!bo) {
                return ResponseVO.fail("修改密码失败！");
            }
            return ResponseVO.success();
        } catch (Exception e) {
            throw new CustomException("修改密码异常", e);
        }
    }

    /**
     * 解锁用户信息
     */
    @PostMapping(value = "/relockUser")
    @OperateLog(title = "用户管理", businessType = BusinessType.OTHER, auditType = AuditType.SYS)
    @PreAuthorize("@ss.hasPermi('system:user:relock')")
    @PreventReplay
    public ResponseVO relockUser(String id) throws CustomException {
        try {
            if (StringUtils.isEmpty(id)) {
                return ResponseVO.fail("id不能为空!");
            }
            // 获取审批表是否存在此操作
            QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
            // 条件：待审批
            wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
            // 条件：删除操作
            wrapper.eq("master_id", id);
            // 条件：实体名
            wrapper.eq("entity_name", "SysUser");
            List<SysApprove> list = sysApproveService.list(wrapper);
            if (list.size() > 0) {
                return ResponseVO.fail("此记录存在未审批的操作,不能进行修改！");
            }
            // id获取用户
            SysUser sysUser = sysUserService.getById(id);
            if (sysUser == null) {
                return ResponseVO.fail("不能解锁用户！");
            }
            if (!"1".equals(sysUser.getStatus())) {
                return ResponseVO.fail("只能对【锁定】状态的进行解锁！");
            }

            boolean bo = sysUserService.relockUserById(Integer.parseInt(id));
            if (bo) {
                return ResponseVO.success("解锁成功");
            } else {
                log.error("解锁失败");
                return ResponseVO.fail("解锁失败");
            }
        } catch (Exception e) {
            throw new CustomException("解锁异常", e);
        }
    }

    /**
     * 用户授权角色
     */
    @PostMapping("/authRole")
    @PreAuthorize("@ss.hasPermi('system:user:role')")
    @OperateLog(title = "用户管理", businessType = BusinessType.GRANT, auditType = AuditType.SYS)
    @PreventReplay
    public ResponseVO authRole(String userId, String roleId) throws CustomException {
        try {
            Long userid;
            if (StringUtils.isNotEmpty(userId)) {
                if (NumberUtil.isLong(userId)){
                    userid = Long.parseLong(userId);
                }
                else{
                    return ResponseVO.fail("用户id不是类型不对！");
                }
            }
            else{
                return ResponseVO.fail("用户id不能为空！");
            }

            Long roleid;
            if (StringUtils.isNotEmpty(roleId)) {
                if (NumberUtil.isLong(roleId)){
                    roleid = Long.parseLong(roleId);
                }
                else{
                    return ResponseVO.fail("角色id不是类型不对！");
                }
            }
            else{
                return ResponseVO.fail("角色id不能为空！");
            }

            // 获取审批表是否存在此操作
            QueryWrapper<SysApprove> wrapper = new QueryWrapper<>();
            // 条件：待审批
            wrapper.eq("approve_status", ApproveStatusEnum.DSP.getCode());
            // 条件：删除操作
            wrapper.eq("master_id", userId);
            // 条件：实体名
            wrapper.eq("entity_name", "SysUser");
            List<SysApprove> list = sysApproveService.list(wrapper);
            if (list.size() > 0) {
                return ResponseVO.fail("此记录存在未审批的操作,不能进行修改！");
            }
            sysUserService.insertUserAuth(userid, roleid);
            return ResponseVO.success("分配角色成功");
        } catch (Exception e) {
            throw new CustomException("分配角色异常", e);
        }
    }

    /**
     * 根据用户ID获取角色
     *
     * @param userId
     * @return
     */
    @GetMapping("/getUserRole")
    @PreventReplay
    public ResponseVO getUserRole(Long userId) throws CustomException {
        try {
            if (userId == null) {
                return ResponseVO.fail("用户id不能为空!");
            }

            QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId);
            SysUserRole sysUserRole = sysUserRoleService.getOne(wrapper);
            return ResponseVO.success(sysUserRole);
        } catch (Exception e) {
            throw new CustomException("获取用户角色异常", e);
        }
    }

    /**
     * 检测用户密码是否符合规则
     *
     * @return 用户信息
     */
    @GetMapping(value = "/validatePasswordRule")
    public ResponseVO validatePasswordRule() throws CustomException {
        try {
            SysUser sysUser = SecurityContextUtil.getSysUser();
            String upwd = CacheConstants.usernamePasswordMap.get(sysUser.getUsername());
            SysPolicy sysPolicy = sysPolicyService.getOne(new QueryWrapper<>());
            String ruleInfo = PasswordRuleUtil.ruleRegx(sysPolicy.getPasswordRule(),upwd);
            return ResponseVO.success(ruleInfo);
        } catch (Exception e) {
            throw new CustomException("检测用户密码是否符合规则异常", e);
        }
    }

}
