package com.njcn.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.config.GeneralInfo;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.PubUtils;
import com.njcn.common.utils.sm.DesUtils;
import com.njcn.common.utils.sm.Sm4Utils;
import com.njcn.db.constant.DbConstant;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.redis.pojo.enums.RedisKeyEnum;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.api.AreaFeignClient;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.user.enums.UserResponseEnum;
import com.njcn.user.enums.UserStatusEnum;
import com.njcn.user.mapper.UserMapper;
import com.njcn.user.mapper.UserRoleMapper;
import com.njcn.user.pojo.constant.UserState;
import com.njcn.user.pojo.constant.UserType;
import com.njcn.user.pojo.dto.UserDTO;
import com.njcn.user.pojo.dto.UserRoleLogsDTO;
import com.njcn.user.pojo.dto.excel.UserExcel;
import com.njcn.user.pojo.param.UserInfoParm;
import com.njcn.user.pojo.param.UserParam;
import com.njcn.user.pojo.po.*;
import com.njcn.user.pojo.vo.UserVO;
import com.njcn.user.service.*;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.File;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2021-12-13
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final IRoleService roleService;

    private final IUserSetService userSetService;

    private final IUserRoleService userRoleService;

    private final UserRoleMapper userRoleMapper;

    private final IUserStrategyService userStrategyService;

    private final IDeptService deptService;

    private final GeneralInfo generalInfo;

    private final DicDataFeignClient dicDataFeignClient;

    private final AreaFeignClient areaFeignClient;

    private final FileStorageUtil fileStorageUtil;

    private final RedisUtil redisUtil;

    @Override
    public UserDTO getUserByName(String loginName) {
        User user = getUserByLoginName(loginName);
        if (Objects.isNull(user)) {
            return null;
        }
        List<String> roleNames = roleService.getRoleNameByUserId(user.getId());
        UserSet userSet = userSetService.lambdaQuery().eq(UserSet::getUserId, user.getId()).one();
        return new UserDTO(user.getId(), user.getLoginName(), user.getName(), user.getPassword(), roleNames, userSet.getSecretKey(), userSet.getStandBy(), user.getDeptId(), user.getType(), user.getHeadSculpture());
    }

    @Override
    public UserDTO loadUserByPhone(String phone) {
        User user = getUserByPhone(phone, false, null);
        if (Objects.isNull(user)) {
            return null;
        }
        List<String> roleNames = roleService.getRoleNameByUserId(user.getId());
        UserSet userSet = userSetService.lambdaQuery().eq(UserSet::getUserId, user.getId()).one();
        return new UserDTO(user.getId(), user.getLoginName(), user.getName(), user.getPassword(), roleNames, userSet.getSecretKey(), userSet.getStandBy(), user.getDeptId(), user.getType(), user.getHeadSculpture());
    }

    @Override
    public void judgeUserStatus(String loginName) {
        User user = getUserByLoginName(loginName);
        if (Objects.isNull(user)) {
            throw new BusinessException(UserResponseEnum.LOGIN_WRONG_PWD);
        }
        //超级管理员则不做任何逻辑判断
        if (user.getType() == 0) {
            //更新用户登录时间，以及错误登录记录的信息归零。
            user.setState(UserState.ENABLE);
            user.setLoginErrorTimes(0);
            user.setLoginTime(LocalDateTime.now());
            user.setFirstErrorTime(null);
            user.setLockTime(null);
            this.baseMapper.updateById(user);
            return;
        }
        //根据用户类型获取对应用户策略
        UserStrategy userStrategy = userStrategyService.lambdaQuery()
                .eq(UserStrategy::getType, user.getCasualUser())
                .eq(UserStrategy::getState, DataStateEnum.ENABLE.getCode())
                .one();
        switch (user.getState()) {
            case UserState.LOCKED:
                LocalDateTime lockTime = user.getLockTime();
                lockTime = lockTime.plusMinutes(userStrategy.getLockPwdTime());
                LocalDateTime nowTime = LocalDateTime.now();
                //判断是否满足锁定时间
                if (nowTime.isBefore(lockTime)) {
                    CommonResponseEnum testEnum = CommonResponseEnum.DYNAMIC_RESPONSE_ENUM;
                    testEnum.setMessage("账号已被锁定:锁定剩余时长" + ChronoUnit.MINUTES.between(nowTime, lockTime) + "分钟");
                    throw new BusinessException(testEnum);
                }
                break;
            case UserState.DELETE:
                //用户已注销
                throw new BusinessException(UserResponseEnum.LOGIN_USER_DELETE);
            case UserState.UNCHECK:
                //用户未审核
                throw new BusinessException(UserResponseEnum.LOGIN_USER_UNAUDITED);
            case UserState.SLEEP:
                //用户已休眠
                throw new BusinessException(UserResponseEnum.LOGIN_USER_SLEEP);
            case UserState.OVERDUE:
                //用户密码已过期
                throw new BusinessException(UserResponseEnum.LOGIN_USER_PASSWORD_EXPIRED);
            default:
                if (user.getPwdState() == 1) {
                    throw new BusinessException(UserResponseEnum.NEED_MODIFY_PWD);
                }
                //用户状态正常，判断其他细节
                judgeFirstLogin(user, userStrategy);
        }
        //所有验证通过后，更新用户登录时间，以及错误登录记录的信息归零。
        user.setState(UserState.ENABLE);
        user.setLoginErrorTimes(0);
        user.setLoginTime(LocalDateTime.now());
        user.setFirstErrorTime(null);
        user.setLockTime(null);
        this.baseMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean addUser(UserParam.UserAddParam addUserParam) {
        /*
         * 检查注册用户的数据是否有重复
         * 1.登录名不能相同
         * 2.手机号不能相同 但手机号可以不填
         */
        if (!Objects.isNull(getUserByLoginName(addUserParam.getLoginName()))) {
            throw new BusinessException(UserResponseEnum.REGISTER_LOGIN_NAME_EXIST);
        }
        if (StringUtils.isNotBlank(addUserParam.getPhone()) && !Objects.isNull(getUserByPhone(addUserParam.getPhone(), false, null))) {
            throw new BusinessException(UserResponseEnum.REGISTER_PHONE_FAIL);
        }
        //sys_user_set表新增数据
        UserSet userSet = userSetService.addUserSet(addUserParam);
        //sys_user表新增数据
        User user = cloneUserBoToUser(addUserParam, userSet);
        //sys_user_role表新增数据
        boolean result = userRoleService.addUserRole(user.getId(), addUserParam.getRole());
        if (result) {
            //获取用户信息
          /*  String userName = RequestUtil.getUsername();
            String index = RequestUtil.getUserIndex();
            String describe = userName + "新增了" + user.getName() + "用户";
            HttpResult<DictData> dicDataByCode = dicDataFeignClient.getDicDataByCode(DicDataEnum.WEB_ADD.getCode());
            DictData data = dicDataByCode.getData();
            //创建对象
            PqsTerminalLogs terminalLogsNew = new PqsTerminalLogs();
            terminalLogsNew.setObjIndex(user.getId());
            terminalLogsNew.setTerminalDescribe(describe);
            terminalLogsNew.setCreateBy(index);
            terminalLogsNew.setCreateTime(LocalDateTime.now());
            terminalLogsNew.setTerminalType(data.getId());
            terminalLogsNew.setState(DataStateEnum.ENABLE.getCode());*/
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateUser(UserParam.UserUpdateParam updateUserParam) {
        if (StringUtils.isNotBlank(updateUserParam.getPhone()) && !Objects.isNull(getUserByPhone(updateUserParam.getPhone(), true, updateUserParam.getId()))) {
            throw new BusinessException(UserResponseEnum.REGISTER_PHONE_FAIL);
        }
        User user = new User();
        BeanUtil.copyProperties(updateUserParam, user);
        //修改用户角色表
        userRoleService.updateUserRole(updateUserParam.getId(), updateUserParam.getRole());
        return this.updateById(user);
    }

    @Override
    public boolean deleteUser(String id) {
        return this.lambdaUpdate()
                .set(User::getState, UserState.DELETE)
                .set(User::getPhone, null)
                .in(User::getId, id)
                .update();
    }

    @Override
    public boolean checkUser(List<String> list) {
        return this.lambdaUpdate()
                .set(User::getState, UserState.ENABLE)
                .in(User::getId, list)
                .update();
    }

    @Override
    public UserVO getUserById(String id) {
        UserVO userVO = new UserVO();
        User user = lambdaQuery().eq(User::getId, id).one();
        if (Objects.isNull(user)) {
            return null;
        }
        BeanUtil.copyProperties(user, userVO);
        if (!Objects.isNull(user.getDeptId()) && StringUtils.isNotBlank(user.getDeptId())) {
            Dept dept = deptService.getDeptById(user.getDeptId());
            //非自定义部门
            if (Objects.equals(dept.getType(), 0)) {
                String areaId = deptService.getAreaIdByDeptId(user.getDeptId());
                userVO.setAreaId(areaId);
                userVO.setAreaName(areaFeignClient.selectIdArea(areaId).getData().getName());
            } else {
                userVO.setAreaName(deptService.getNameByDeptId(user.getDeptId()));
            }
            userVO.setDeptName(deptService.getNameByDeptId(user.getDeptId()));
            userVO.setDeptLevel(dept.getPids().split(StrUtil.COMMA).length);
        }
        List<String> roleList = roleService.getIdByUserId(id);
        userVO.setRoleList(roleList);
        userVO.setRole(roleService.getNameByUserId(id));
        userVO.setRoleCode(roleService.getCodeByList(roleList));
        return userVO;
    }

    @Override
    public Page<UserVO> userList(UserParam.UserQueryParam queryParam) {
        QueryWrapper<UserVO> queryWrapper = new QueryWrapper<>();
        Page<UserVO> page = new Page<>();
        User user = this.lambdaQuery().eq(User::getId, RequestUtil.getUserIndex()).one();
        Integer type = user.getType();
        List<Integer> types = new ArrayList<>();
        List<String> roleCodeList = roleService.getRoleNameByUserId(user.getId());
        //超级管理员，展示所有用户信息（不包含root）
        if (Objects.equals(UserType.SUPER_ADMINISTRATOR, type)) {
            types.addAll(Arrays.asList(UserType.ADMINISTRATOR, UserType.USER, UserType.APP));
        }
        //业务管理员，展示web用户
        else if (Objects.equals(UserType.ADMINISTRATOR, type) && !roleCodeList.contains("operation_manager")) {
            types.addAll(Arrays.asList(UserType.USER));
        }
        //运维管理员，展示web用户、App用户
        else if (Objects.equals(UserType.ADMINISTRATOR, type) && roleCodeList.contains("operation_manager")) {
            types.addAll(Arrays.asList(UserType.USER, UserType.APP));
        }
        if (ObjectUtil.isNotNull(queryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(queryParam.getSearchValue())) {
                //用户表提供用户名、登录名 模糊查询
                queryWrapper
                        .and(param -> param.like("sys_user.name", queryParam.getSearchValue())
                                .or().like("sys_user.login_Name", queryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equalsIgnoreCase(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //默认根据最后登录时间排序
                queryWrapper.orderBy(true, false, "sys_user.login_time");
            }
        }
        queryWrapper.in("sys_user.type", types);
        page = this.baseMapper.page(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper, queryParam.getSearchState(), queryParam.getCasualUser());
        page.getRecords().forEach(item -> {
            item.setRoleList(roleService.getIdByUserId(item.getId()));
            item.setRole(roleService.getNameByUserId(item.getId()));
        });
        return page;
    }

    @Override
    public Page<UserVO> checkUserList(UserParam.UserQueryParam queryParam) {
        QueryWrapper<UserVO> queryWrapper = new QueryWrapper<>();
        Page<UserVO> page = new Page<>();
        Integer type = this.lambdaQuery().eq(User::getId, RequestUtil.getUserIndex()).one().getType();
        if (Objects.equals(UserType.SUPER_ADMINISTRATOR, type)) {
            type = UserType.ADMINISTRATOR;
        } else if (Objects.equals(UserType.ADMINISTRATOR, type)) {
            type = UserType.USER;
        } else if (Objects.equals(UserType.USER, type)) {
            return page;
        }
        if (ObjectUtil.isNotNull(queryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(queryParam.getSearchValue())) {
                //用户表提供用户名、登录名 模糊查询
                queryWrapper
                        .and(param -> param.like("sys_user.name", queryParam.getSearchValue())
                                .or().like("sys_user.login_Name", queryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equalsIgnoreCase(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //默认根据注册时间排序
                queryWrapper.orderBy(true, queryParam.getOrderBy().equalsIgnoreCase(DbConstant.ASC), "sys_user.register_Time");
            }
        }
        queryWrapper.eq("sys_user.type", type).eq("sys_user.state", UserState.UNCHECK);
        page = this.baseMapper.checkPage(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper);
        page.getRecords().forEach(item -> {
            item.setRole(roleService.getNameByUserId(item.getId()));
        });
        return page;
    }

    @Override
    public boolean updatePassword(String id, String password) {
        String secretPassword = userSetService.updatePassword(id, password, true);
        User user = lambdaQuery().eq(User::getId, id).one();
        user.setPassword(secretPassword);
        user.setPwdValidity(LocalDateTime.now());
        user.setLoginTime(LocalDateTime.now());
        return this.updateById(user);
    }

    @Override
    public String updateUserLoginErrorTimes(String loginName) {
        User user = this.lambdaQuery().eq(User::getLoginName, loginName).one();
        LocalDateTime now = LocalDateTime.now();
        if (Objects.nonNull(user)) {
            UserStrategy userStrategy = userStrategyService.getUserStrategy(user.getCasualUser());
            Integer loginErrorTimes = user.getLoginErrorTimes();
            ++loginErrorTimes;
            if (Objects.isNull(user.getFirstErrorTime())) {
                //首次错误，错误1次、记录第一次错误时间
                user.setLoginErrorTimes(loginErrorTimes);
                user.setFirstErrorTime(LocalDateTime.now());
            } else if (loginErrorTimes <= userStrategy.getLimitPwdTimes()) {
                //如果次数在策略之内，还未被锁定
                LocalDateTime firstErrorTime = user.getFirstErrorTime();
                firstErrorTime = firstErrorTime.plusMinutes(userStrategy.getLockPwdCheck());
                if (now.isAfter(firstErrorTime)) {
                    //重置密码错误次数、时间等记录
                    user.setLoginErrorTimes(1);
                    user.setFirstErrorTime(LocalDateTime.now());
                } else {
                    user.setLoginErrorTimes(loginErrorTimes);
                }
            } else {
                user.setLockTime(LocalDateTime.now());
                user.setState(UserStatusEnum.LOCKED.getCode());
                user.setLoginErrorTimes(loginErrorTimes);
                this.baseMapper.updateById(user);
                return UserResponseEnum.LOGIN_USER_LOCKED.getMessage();
            }
            this.baseMapper.updateById(user);
        }
        return CommonResponseEnum.SUCCESS.getMessage();
    }

    @Override
    public boolean passwordConfirm(String password) {
        //当前用户加密密码
        String secretPassword = this.lambdaQuery().eq(User::getId, RequestUtil.getUserIndex()).one().getPassword();
        String decryptPassword = userSetService.getDecryptPassword(password);
        UserSet userSet = userSetService.getUserSetByUserId(RequestUtil.getUserIndex());
        String secretKey = userSet.getSecretKey();
        Sm4Utils sm4 = new Sm4Utils(secretKey);
        String mPwd = sm4.encryptData_ECB(decryptPassword);
        //二次确认加密密码
        String secondSecretPassword = sm4.encryptData_ECB(mPwd + secretKey);
        return Objects.equals(secretPassword, secondSecretPassword);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateFirstPassword(String secretName, String password, String ip) {
        String loginName = DesUtils.aesDecrypt(secretName);
        User user = this.lambdaQuery().eq(User::getLoginName, loginName).one();
        String secretPassword = userSetService.updateFirstPassword(user.getId(), password, loginName, ip);
        user.setPassword(secretPassword);
        user.setPwdState(UserState.NEEDLESS);
        return this.updateById(user);
    }

    @Override
    public String exportUser(UserParam.UserQueryParam queryParam, String methodDescribe) {
        QueryWrapper<UserExcel> queryWrapper = new QueryWrapper<>();
        List<UserExcel> userExcels;
        String fileName = methodDescribe + ".xlsx";
        String targetDir = generalInfo.getBusinessTempPath() + File.separator + RequestUtil.getUserIndex();
        File parentDir = new File(targetDir);
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        File excel = new File(targetDir, fileName);
        Integer type = this.lambdaQuery().eq(User::getId, RequestUtil.getUserIndex()).one().getType() + 1;
        if (ObjectUtil.isNotNull(queryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(queryParam.getSearchValue())) {
                //用户表提供用户名、登录名 模糊查询
                queryWrapper
                        .and(param -> param.like("sys_user.name", queryParam.getSearchValue())
                                .or().like("sys_user.login_Name", queryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equalsIgnoreCase(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //默认根据最后登录时间排序
                queryWrapper.orderBy(true, false, "sys_user.login_time");
            }
        }
        queryWrapper.eq("sys_user.type", type);
        userExcels = this.baseMapper.queryExportUser(queryWrapper);
        if (CollectionUtil.isEmpty(userExcels)) {
            userExcels = new ArrayList<>();
        } else {
            userExcels = userExcels.stream().peek(userExcel -> {
                userExcel.setRole(String.join(",", roleService.getNameByUserId(userExcel.getId())));
            }).collect(Collectors.toList());
        }
        ExcelUtil.exportExcelWithTargetFile(excel, UserExcel.class, userExcels);
        return FileUtil.getAbsolutePath(excel);
    }

    @Override
    public boolean activateUser(String id) {
        User user = this.lambdaQuery().eq(User::getId, id).one();
        user.setPwdValidity(LocalDateTime.now());
        user.setLoginTime(LocalDateTime.now());
        user.setState(UserState.ENABLE);
        user.setLoginErrorTimes(0);
        user.setFirstErrorTime(null);
        return this.updateById(user);
    }

    @Override
    public List<User> getMarketList() {
        Role roleByCode = roleService.getRoleByCode(AppRoleEnum.MARKET_USER.getCode());
        List<UserRole> userRoles = userRoleMapper.selectUserRole(
                Collections.singletonList(roleByCode.getId())
        );
        List<String> userIds = userRoles.stream()
                .map(UserRole::getUserId)
                .collect(Collectors.toList());

        if (userIds.isEmpty()) {
            return Collections.emptyList();
        }

        return this.lambdaQuery()
                .ne(User::getState, UserState.DELETE)
                .in(User::getId, userIds)
                .list();
    }

    @Override
    public List<UserVO> getFormalUserList() {
        List<UserVO> users = new ArrayList<>();
        Role roleByCode1 = roleService.getRoleByCode(AppRoleEnum.ENGINEERING_USER.getCode());
        Role roleByCode2 = roleService.getRoleByCode(AppRoleEnum.MARKET_USER.getCode());
        List<UserRole> userRoles = userRoleMapper.selectUserRole(
                Stream.of(roleByCode1.getId()
                        ,roleByCode2.getId()
                ).collect(Collectors.toList()));
        List<String> collect = userRoles.stream().map(UserRole::getUserId).distinct().collect(Collectors.toList());

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(User::getState, Arrays.asList(1,2,4,5))
                .in(User::getType,Arrays.asList(2,3));
        List<User> users1 = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(users1)) {
            users1.forEach(item->{
                //剔除工程 营销用户
                if (collect.contains(item.getId())) {
                    return;
                }
                UserVO userVO = new UserVO();
                userVO.setId(item.getId());
                userVO.setName(item.getName());
                users.add(userVO);
            });
        }
        return users;
    }

    @Override
    public List<User> getUserListByDeptId(String deptId) {
        LambdaQueryWrapper<Dept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Dept::getPids, deptId).select(Dept::getId);
        List<String> deptIds = new ArrayList<>();
        deptIds.add(deptId);
        List<Dept> deptList = deptService.list(lambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(deptIds)) {
            deptIds.addAll(deptList.stream().map(Dept::getId).distinct().collect(Collectors.toList()));
        }
        return this.list(new LambdaQueryWrapper<User>().in(User::getDeptId, deptIds).select(User::getId, User::getName, User::getLoginName));
    }

    @Override
    public boolean updateAppUser(UserInfoParm userInfoParm) {
        return this.lambdaUpdate().eq(User::getId, RequestUtil.getUserIndex()).
                set(StringUtils.isNotBlank(userInfoParm.getName()), User::getName, userInfoParm.getName()).
                set(StringUtils.isNotBlank(userInfoParm.getHeadSculpture()), User::getHeadSculpture, userInfoParm.getHeadSculpture()).update();
    }

    @Override
    public String uploadImage(MultipartFile issuesFile) {

        return fileStorageUtil.uploadMultipart(issuesFile, OssPath.RESOURCEDATA);

    }

    @Override
    public String getUrl(String headSculpture) {
        return fileStorageUtil.getFileUrl(headSculpture);
    }

    @Override
    public List<User> getUserListByRoleCode(String roleCode) {
        return userRoleMapper.selectUserRoleCode(roleCode);
    }

    @Override
    public List<User> getUserByRoleType(Integer roleType) {
        return userRoleMapper.getUserByRoleType(roleType);
    }

    @Override
    public List<UserVO> listAllUserByDeptId(String deptId) {
        //查询所有状态正常的用户信息，目前只要id和name
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(deptId)) {
            lambdaQueryWrapper.eq(User::getDeptId, deptId);
        }
        lambdaQueryWrapper.eq(User::getState, DataStateEnum.ENABLE.getCode())
                .select(User::getName, User::getId);
        List<User> users = this.baseMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(users)) {
            return new ArrayList<>();
        } else {
            return BeanUtil.copyToList(users, UserVO.class);
        }
    }

    @Override
    public List<UserVO> getUserVOByIdList(List<String> ids) {
        //查询所有状态正常的用户信息，目前只要id和name
        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        List<UserVO> list = this.baseMapper.getUserVOByIdList(ids);
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(item->{
                List<Role> roles = userRoleService.getRoleListByUserId(item.getId());
                item.setRoleList(roles.stream().map(Role::getId).collect(Collectors.toList()));
                item.setRoleCode(roles.stream().map(Role::getCode).collect(Collectors.toList()));
            });
        }
        return list;
    }

    @Override
    public List<String> getUserIdByRoleId(List<String> roleId) {
        LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.in(UserRole::getRoleId, roleId);
        List<UserRole> userRole = userRoleService.list(userRoleLambdaQueryWrapper);
        if (CollectionUtil.isEmpty(userRole)) {
            return new ArrayList<>();
        } else {
            return userRole.stream().map(UserRole::getUserId).distinct().collect(Collectors.toList());
        }
    }

    @Override
    public List<User> simpleList(Boolean allUserFlag) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.select(User::getId, User::getName,User::getLoginName).eq(User::getState, DataStateEnum.ENABLE.getCode());
        if(!allUserFlag){
            userLambdaQueryWrapper.eq(User::getType,2);
        }
        return this.baseMapper.selectList(userLambdaQueryWrapper);
    }

    @Override
    public List<String> getColleaguesIdByUserId(String id) {
        User user = this.baseMapper.selectById(id);
        //根据当前部门id获取所有子部门的id,包含当前用户部门
        List<String> deptIds = deptService.getDepSonIdtByDeptId(user.getDeptId());
        //获取这些部门下所有的用户id
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.select(User::getId).in(User::getDeptId,deptIds);
        List<User> userList = this.baseMapper.selectList(userLambdaQueryWrapper);
        //所有用户的id
        return userList.stream().map(User::getId).collect(Collectors.toList());
    }

    @Override
    public Boolean userRoleList() {
        JSONObject jsonObject = new JSONObject();
        List<UserRoleLogsDTO> mapList = this.baseMapper.userRoleList();
        for(UserRoleLogsDTO item :mapList){
            jsonObject.putOpt(item.getLoginName(),item.getRoleType());
        }
        redisUtil.saveByKeyWithExpire(RedisKeyEnum.USER_ROLE_TYPE_KEY.getKey(),jsonObject,-1L);
        return true;
    }

    /**
     * 根据登录名查询用户
     *
     * @param loginName 登录名
     * @return 用户信息
     */
    private User getUserByLoginName(String loginName) {
        return lambdaQuery()
                .eq(User::getLoginName, loginName)
                .one();
    }

    /**
     * 根据手机号查询用户
     *
     * @param phone 手机号码
     * @return 用户信息
     */
    private User getUserByPhone(String phone, boolean result, String id) {
        if (result) {
            return lambdaQuery()
                    .eq(User::getPhone, phone)
                    .ne(User::getId, id)
                    .one();
        } else {
            return lambdaQuery()
                    .eq(User::getPhone, phone)
                    .one();
        }
    }


    /**
     * 判断是否需要修改密码
     */
    private void judgeFirstLogin(@NotNull User user, UserStrategy userStrategy) {
        if (user.getPwdState() == 1) {
            throw new BusinessException(UserResponseEnum.NEED_MODIFY_PWD);
        } else {
            judgeIp(user, userStrategy);
        }
    }

    /**
     * 判断用户是否在合理的IP内登录
     */
    private void judgeIp(@NotNull User user, UserStrategy userStrategy) {
        String ipSection = user.getLimitIpStart() + "-" + user.getLimitIpEnd();
        log.error("用户实际ip:" + RequestUtil.getRealIp());
        log.error("用户限制ip:" + ipSection);
        if (RequestUtil.getRealIp().equalsIgnoreCase(LogInfo.UNKNOWN_IP)) {
            //feign接口可能获取的IP是空的
            throw new BusinessException(UserResponseEnum.INVALID_IP);
        } else if (!PubUtils.ipExistsInRange(RequestUtil.getRealIp(), ipSection)) {
            throw new BusinessException(UserResponseEnum.INVALID_IP);
        } else {
            judgeLimitTime(user, userStrategy);
        }
        judgeLimitTime(user, userStrategy);
    }

    /**
     * 判断用户是否在允许的时间段内登录
     */
    private void judgeLimitTime(@NotNull User user, UserStrategy userStrategy) {
        int nowHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        String[] limitTime = user.getLimitTime().split(StrUtil.DASHED);
        if (nowHour >= Integer.parseInt(limitTime[0]) && nowHour < Integer.parseInt(limitTime[1])) {
            judgePwdTimeValidity(user, userStrategy);
        } else {
            throw new BusinessException(UserResponseEnum.INVALID_TIME);
        }
    }

    /**
     * 判断用户密码是否已经过期
     */
    private void judgePwdTimeValidity(@NotNull User user, UserStrategy userStrategy) {
        LocalDateTime pwdValidity = user.getPwdValidity();
        pwdValidity = pwdValidity.plusMonths(userStrategy.getLimitPwdDate());
        if (LocalDateTime.now().isBefore(pwdValidity)) {
            judgeLeisurePwd(user, userStrategy);
        } else {
            //将用户状态置为过期
            user.setState(UserState.OVERDUE);
            this.baseMapper.updateById(user);
            throw new BusinessException(UserResponseEnum.LOGIN_USER_PASSWORD_EXPIRED);
        }

    }

    /**
     * 判断用户闲置
     */
    private void judgeLeisurePwd(@NotNull User user, UserStrategy userStrategy) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime sleepTime = user.getLoginTime().plusDays(userStrategy.getSleep());
        LocalDateTime logoutTime = user.getLoginTime().plusDays(userStrategy.getLogout());
        if (now.isAfter(sleepTime) && now.isBefore(logoutTime)) {
            //将用户状态置为休眠
            user.setState(UserState.SLEEP);
            this.baseMapper.updateById(user);
            throw new BusinessException(UserResponseEnum.LOGIN_USER_SLEEP);
        } else if (now.isAfter(logoutTime)) {
            //将用户状态置为注销
            user.setState(UserState.DELETE);
            this.baseMapper.updateById(user);
            throw new BusinessException(UserResponseEnum.LOGIN_USER_DELETE);
        }
    }


    /**
     * sys_user表新增数据
     *
     * @param addUserParam 新增用户信息
     * @param userSet      用户配置信息
     */
    private User cloneUserBoToUser(UserParam.UserAddParam addUserParam, UserSet userSet) {
        User user = new User();
        BeanUtil.copyProperties(addUserParam, user);
        //设置用户id
        user.setId(userSet.getUserId());
        //对密码做处理 SM4加密(SM4_1密码+工作秘钥）
        String secretKey = userSet.getSecretKey();
        Sm4Utils sm4 = new Sm4Utils(secretKey);
        user.setPassword(sm4.encryptData_ECB(userSet.getStandBy() + secretKey));
        //新建用户为管理员时，默认部门为顶级部门
        if (Objects.equals(addUserParam.getType(), UserType.ADMINISTRATOR)) {
            user.setDeptId(deptService.getTopDeptId());
        }
        //填写一些默认值
        user.setState(UserState.UNCHECK);
        user.setOrigin(UserState.NORMAL_ORIGIN);
        user.setPwdState(UserState.NEED);
        user.setRegisterTime(LocalDateTime.now());
        user.setLoginTime(LocalDateTime.now());
        user.setPwdValidity(LocalDateTime.now());
        user.setLoginErrorTimes(UserState.ERROR_PASSWORD_TIMES);
        user.setReferralCode(PubUtils.randomCode(6));
        this.save(user);
        return user;
    }
}
