package cn.ey.biz.module.system.service.user;

import cn.ey.biz.common.enums.CommonStatusEnum;
import cn.ey.biz.common.exception.ServiceException;
import cn.ey.biz.common.pojo.PageResult;
import cn.ey.biz.common.util.collection.CollectionUtils;
import cn.ey.biz.framework.mybatis.core.util.MyBatisUtils;
import cn.ey.biz.module.system.api.file.FileApi;
import cn.ey.biz.module.system.api.user.dto.UserSyncFullDataReqDTO;
import cn.ey.biz.module.system.api.user.dto.UsersForConditionsReqDTO;
import cn.ey.biz.module.system.api.user.dto.UsersForLastDateTimeReqDTO;
import cn.ey.biz.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.ey.biz.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.ey.biz.module.system.controller.admin.user.vo.user.*;
import cn.ey.biz.module.system.convert.user.UserConvert;
import cn.ey.biz.module.system.dal.dataobject.dept.DeptDO;
import cn.ey.biz.module.system.dal.dataobject.dept.UserPostDO;
import cn.ey.biz.module.system.dal.dataobject.sync.DataSyncRecordDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserDO;
import cn.ey.biz.module.system.dal.dataobject.user.AdminUserES;
import cn.ey.biz.module.system.dal.dataobject.user.UserSyncTempDO;
import cn.ey.biz.module.system.dal.mapper.codeblock.CodeBlockMapper;
import cn.ey.biz.module.system.dal.mapper.dept.UserPostMapper;
import cn.ey.biz.module.system.dal.mapper.sync.DataSyncRecordMapper;
import cn.ey.biz.module.system.dal.mapper.user.AdminUserMapper;
import cn.ey.biz.module.system.dal.mapper.user.UserSyncTempMapper;
import cn.ey.biz.module.system.dal.redis.RedisKeyConstants;
import cn.ey.biz.module.system.enums.DataSyncConstans;
import cn.ey.biz.module.system.enums.sync.*;
import cn.ey.biz.module.system.service.dept.DeptService;
import cn.ey.biz.module.system.service.dept.PostService;
import cn.ey.biz.module.system.service.dict.DictGradeRateRefService;
import cn.ey.biz.module.system.service.permission.PermissionService;
import cn.ey.biz.module.system.service.tenant.TenantService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;
import static cn.ey.biz.common.util.collection.CollectionUtils.convertList;
import static cn.ey.biz.common.util.collection.CollectionUtils.convertSet;
import static cn.ey.biz.module.system.enums.ErrorCodeConstants.*;

/**
 * 后台用户 Service 实现类
 */
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUserDO> implements AdminUserService {


    @Value("${sys.user.init-password:ey123}")
    private String userInitPassword;

    @Resource
    private AdminUserMapper userMapper;

    @Resource
    private DeptService deptService;
    @Resource
    private PostService postService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    @Lazy // 延迟，避免循环依赖报错
    private TenantService tenantService;

    @Resource
    private UserPostMapper userPostMapper;

    @Resource
    private FileApi fileApi;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private DataSyncRecordMapper dataSyncRecordMapper;

    @Resource
    private UserSyncTempMapper userSyncTempMapper;

    @Resource
    private CodeBlockMapper codeBlockMapper;

    @Resource
    DictGradeRateRefService dictGradeRateRefService;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUser(UserCreateReqVO reqVO) {
        // 校验账户配合
        tenantService.handleTenantInfo(tenant -> {
            long count = userMapper.selectCount();
            if (count >= tenant.getAccountCount()) {
                throw exception(USER_COUNT_MAX, tenant.getAccountCount());
            }
        });
        // 校验正确性
        checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
                reqVO.getDeptId(), reqVO.getPostIds());
        // 插入用户
        AdminUserDO user = UserConvert.INSTANCE.convert(reqVO);
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(passwordEncoder.encode(reqVO.getPassword())); // 加密密码
        userMapper.insert(user);
        // 插入关联岗位
        if (CollectionUtil.isNotEmpty(user.getPostIds())) {
            userPostMapper.insertBatch(convertList(user.getPostIds(),
                    postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
        }
        return user.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(UserUpdateReqVO reqVO) {
        // 校验正确性
        checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
                reqVO.getDeptId(), reqVO.getPostIds());
        // 更新用户
        AdminUserDO updateObj = UserConvert.INSTANCE.convert(reqVO);
        userMapper.updateById(updateObj);
        // 更新岗位
        updateUserPost(reqVO, updateObj);
    }

    private void updateUserPost(UserUpdateReqVO reqVO, AdminUserDO updateObj) {
        Long userId = reqVO.getId();
        Set<Long> dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
        // 计算新增和删除的岗位编号
        Set<Long> postIds = updateObj.getPostIds();
        Collection<Long> createPostIds = CollUtil.subtract(postIds, dbPostIds);
        Collection<Long> deletePostIds = CollUtil.subtract(dbPostIds, postIds);
        // 执行新增和删除。对于已经授权的菜单，不用做任何处理
        if (!CollectionUtil.isEmpty(createPostIds)) {
            userPostMapper.insertBatch(convertList(createPostIds,
                    postId -> new UserPostDO().setUserId(userId).setPostId(postId)));
        }
        if (!CollectionUtil.isEmpty(deletePostIds)) {
            userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds);
        }
    }

    @Override
    public void updateUserLogin(Long id, String loginIp) {
        userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
    }

    @Override
    public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) {
        // 校验正确性
        checkUserExists(id);
        checkEmailUnique(id, reqVO.getEmail());
        checkMobileUnique(id, reqVO.getMobile());
        // 执行更新
        userMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id));
    }

    @Override
    public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
        // 校验旧密码密码
        checkOldPassword(id, reqVO.getOldPassword());
        // 执行更新
        AdminUserDO updateObj = new AdminUserDO().setId(id);
        updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码
        userMapper.updateById(updateObj);
    }

    @Override
    public String updateUserAvatar(Long id, InputStream avatarFile) throws Exception {
        checkUserExists(id);
        // 存储文件
        String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
        // 更新路径
        AdminUserDO sysUserDO = new AdminUserDO();
        sysUserDO.setId(id);
        sysUserDO.setAvatar(avatar);
        userMapper.updateById(sysUserDO);
        return avatar;
    }

    @Override
    public void updateUserPassword(Long id, String password) {
        // 校验用户存在
        checkUserExists(id);
        // 更新密码
        AdminUserDO updateObj = new AdminUserDO();
        updateObj.setId(id);
        updateObj.setPassword(encodePassword(password)); // 加密密码
        userMapper.updateById(updateObj);
    }

    @Override
    @Transactional
    public void updateUserStatus(Long id, Integer status) {
        // 校验用户存在
        checkUserExists(id);
        // 更新状态
        AdminUserDO updateObj = new AdminUserDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        userMapper.updateById(updateObj);

        //更新es 状态
        Map<String,Integer> map=new HashMap<>();
        map.put("status",status);
        UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(id)).withDocument(Document.from(map)).build();
        IndexCoordinates of = IndexCoordinates.of(
                AdminUserES.class.getAnnotation(org.springframework.data.elasticsearch.annotations.Document.class ).indexName()
        );
        elasticsearchRestTemplate.update(updateQuery,of);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long id) {
        // 校验用户存在
        checkUserExists(id);
        // 删除用户
        userMapper.deleteById(id);
        // 删除用户关联数据
        permissionService.processUserDeleted(id);
        // 删除用户岗位
        userPostMapper.deleteByUserId(id);
    }

    @Override
    public AdminUserDO getUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public AdminUserDO getUserByMobile(String mobile) {
        return userMapper.selectByMobile(mobile);
    }

    @Override
    public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
        return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()));
    }

    @Override
    public PageResult<AdminUserDO> getUserPageList(UserPageTreeReqVO reqVO) {
        reqVO.setDeptIds(getDeptCondition(reqVO.getDeptId()));
        if (CollectionUtil.isEmpty(reqVO.getServiceLineTree())) {
            reqVO.setServiceLineTree(null);
        }
        if (CollectionUtil.isEmpty(reqVO.getRegionTree())) {
            reqVO.setRegionTree(null);
        }
        IPage<Object> page = MyBatisUtils.buildPage(reqVO);
        IPage<AdminUserDO> userPageList = userMapper.getUserPageList(page, reqVO);
        return new PageResult<>(userPageList.getRecords(), userPageList.getTotal());
    }

    @Override
    public AdminUserDO getUser(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public List<AdminUserDO> getUsersByDeptIds(Collection<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return Collections.emptyList();
        }
        return userMapper.selectListByDeptIds(deptIds);
    }

    @Override
    public List<AdminUserDO> getUsersByPostIds(Collection<Long> postIds) {
        if (CollUtil.isEmpty(postIds)) {
            return Collections.emptyList();
        }
        Set<Long> userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId);
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        return userMapper.selectBatchIds(userIds);
    }

    @Override
    public List<AdminUserDO> getUsers(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }

        return userMapper.selectBatchIds(ids);
    }

    @Override
    public void validUsers(Set<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        // 获得岗位信息
        List<AdminUserDO> users = userMapper.selectBatchIds(ids);
        Map<Long, AdminUserDO> userMap = CollectionUtils.convertMap(users, AdminUserDO::getId);
        // 校验
        ids.forEach(id -> {
            AdminUserDO user = userMap.get(id);
            if (user == null) {
                throw exception(USER_NOT_EXISTS);
            }
            if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) {
                throw exception(USER_IS_DISABLE, user.getNickname());
            }
        });
    }

    @Override
    public List<AdminUserDO> getUsers(UserExportReqVO reqVO) {
        return userMapper.selectList(reqVO, getDeptCondition(reqVO.getDeptId()));
    }

    @Override
    public List<AdminUserDO> getUsersByNickname(String nickname) {
        return userMapper.selectListByNickname(nickname);
    }

    @Override
    public List<AdminUserDO> getUsersByUsername(String username) {
        return userMapper.selectListByUsername(username);
    }

    /**
     * 获得部门条件：查询指定部门的子部门编号们，包括自身
     *
     * @param deptId 部门编号
     * @return 部门编号集合
     */
    private Set<Long> getDeptCondition(Long deptId) {
        if (deptId == null) {
            return Collections.emptySet();
        }
        Set<Long> deptIds = convertSet(deptService.getDeptsByParentIdFromCache(
                deptId, true), DeptDO::getId);
        deptIds.add(deptId); // 包括自身
        return deptIds;
    }

    private void checkCreateOrUpdate(Long id, String username, String mobile, String email,
                                     Long deptId, Set<Long> postIds) {
        // 校验用户存在
        checkUserExists(id);
        // 校验用户名唯一
        checkUsernameUnique(id, username);
        // 校验手机号唯一
        checkMobileUnique(id, mobile);
        // 校验邮箱唯一
        checkEmailUnique(id, email);
        // 校验部门处于开启状态
        deptService.validDepts(CollectionUtils.singleton(deptId));
        // 校验岗位处于开启状态
        postService.validPosts(postIds);
    }

    @VisibleForTesting
    public void checkUserExists(Long id) {
        if (id == null) {
            return;
        }
        AdminUserDO user = userMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
    }

    @VisibleForTesting
    public void checkUsernameUnique(Long id, String username) {
        if (StrUtil.isBlank(username)) {
            return;
        }
        AdminUserDO user = userMapper.selectByUsername(username);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_USERNAME_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_USERNAME_EXISTS);
        }
    }

    @VisibleForTesting
    public void checkEmailUnique(Long id, String email) {
        if (StrUtil.isBlank(email)) {
            return;
        }
        AdminUserDO user = userMapper.selectByEmail(email);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_EMAIL_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_EMAIL_EXISTS);
        }
    }

    @VisibleForTesting
    public void checkMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        AdminUserDO user = userMapper.selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_EXISTS);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_MOBILE_EXISTS);
        }
    }

    /**
     * 校验旧密码
     *
     * @param id          用户 id
     * @param oldPassword 旧密码
     */
    @VisibleForTesting
    public void checkOldPassword(Long id, String oldPassword) {
        AdminUserDO user = userMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        if (!isPasswordMatch(oldPassword, user.getPassword())) {
            throw exception(USER_PASSWORD_FAILED);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public UserImportRespVO importUsers(List<UserImportExcelVO> importUsers, boolean isUpdateSupport) {
        if (CollUtil.isEmpty(importUsers)) {
            throw exception(USER_IMPORT_LIST_IS_EMPTY);
        }
        UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
        importUsers.forEach(importUser -> {
            // 校验，判断是否有不符合的原因
            try {
                checkCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(),
                        importUser.getDeptId(), null);
            } catch (ServiceException ex) {
                respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
                return;
            }
            // 判断如果不存在，在进行插入
            AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
            if (existUser == null) {
                userMapper.insert(UserConvert.INSTANCE.convert(importUser)
                        .setPassword(encodePassword(userInitPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
                respVO.getCreateUsernames().add(importUser.getUsername());
                return;
            }
            // 如果存在，判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg());
                return;
            }
            AdminUserDO updateUser = UserConvert.INSTANCE.convert(importUser);
            updateUser.setId(existUser.getId());
            userMapper.updateById(updateUser);
            respVO.getUpdateUsernames().add(importUser.getUsername());
        });
        return respVO;
    }

    @Override
    public List<AdminUserDO> getUsersByStatus(Integer status) {
        return userMapper.selectListByStatus(status);
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    @Override
    public AdminUserDO selectByUserCode(String userCode) {
        //查询redis
        String userRedisKey = String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), userCode);
        AdminUserDO adminUserDO = (AdminUserDO) redisTemplate.opsForValue().get(userRedisKey);
        if (adminUserDO != null) {
            return adminUserDO;
        }
        //查询数据库
        adminUserDO = userMapper.selectByUserCode(userCode);
        if (adminUserDO == null) {
            return null;
        }
        //缓存到redis
        saveRedis(adminUserDO);
        return adminUserDO;
    }

    private void saveRedis(AdminUserDO adminUserDO){
        //且放到缓存,过期时间24小时,
        //key:gpn
        redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), adminUserDO.getGpn()),
                adminUserDO, RedisKeyConstants.SYSTEM_USER.getTimeout());
        //key:公司邮箱
        redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), adminUserDO.getBusinessEmail()),
                adminUserDO, RedisKeyConstants.SYSTEM_USER.getTimeout());
    }

    @Override
    public AdminUserDO getUserForGpnOrEmail(String gpn, String businessEmail) {
        //  如果参数全部为空，返回null
        if (StringUtils.isBlank(gpn) && StringUtils.isBlank(businessEmail)) {
            throw exception(USER_GPN_EMAIL_EXISTS);
        }
        //根据参数转换 redis key
        String userRedisKey = null;
        if (StringUtils.isNotBlank(gpn) && StringUtils.isNotBlank(businessEmail)) {
            //如果两者都存在，默认按gpn取
            userRedisKey = String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), gpn);
        } else if (StringUtils.isNotBlank(gpn)) {
            userRedisKey = String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), gpn);
        } else if (StringUtils.isNotBlank(businessEmail)) {
            userRedisKey = String.format(RedisKeyConstants.SYSTEM_USER.getKeyTemplate(), businessEmail);
        }
        AdminUserDO adminUserDO = (AdminUserDO) redisTemplate.opsForValue().get(userRedisKey);
        if (adminUserDO != null) {
            return adminUserDO;
        }
        //缓存没有，则读库，
        LambdaQueryWrapper<AdminUserDO> lqw = Wrappers.lambdaQuery(AdminUserDO.class)
                .eq(StringUtils.isNotBlank(gpn), AdminUserDO::getGpn, gpn)
                .eq(StringUtils.isNotBlank(businessEmail), AdminUserDO::getBusinessEmail, businessEmail);
        adminUserDO = userMapper.selectOne(lqw);
        if (adminUserDO == null) {
            return null;
        }
        //缓存到redis
        saveRedis(adminUserDO);
        return adminUserDO;
    }

    @Override
    public List<AdminUserDO> getUserForGui(Collection<String> gui) {
        LambdaQueryWrapper<AdminUserDO> lqw = Wrappers.lambdaQuery(AdminUserDO.class)
                .in(AdminUserDO::getGui, gui)
                .eq(AdminUserDO::getEmployeeStatus, "A");
        return userMapper.selectList(lqw);
    }


    @Override
    public List<AdminUserDO> getUsersForLastDateTime(UsersForLastDateTimeReqDTO uReqDTO) {

        LocalDateTime start = DateUtil.parseLocalDateTime(uReqDTO.getUpdateStartDateTime());
        LocalDateTime end = DateUtil.parseLocalDateTime(uReqDTO.getUpdateEndDateTime());
        long betweenSeconds = LocalDateTimeUtil.between(start, end, ChronoUnit.SECONDS);
        //间隔时间不能大于24小时
        if (betweenSeconds > (60 * 60 * 24)) {
            throw exception(USER_BETWEEN_SECONDS_MAX);
        }
        //结束时间不能大于当前时间
        if (!LocalDateTime.now().isAfter(end)) {
            throw exception(USER_END_DATE_TIME_AFTER);
        }
        LambdaQueryWrapper<AdminUserDO> wrapper = Wrappers.lambdaQuery(AdminUserDO.class)
                .eq(AdminUserDO::getIsOverseasStaff,0)
                .and(wrapper1 ->
                    wrapper1.ge(AdminUserDO::getCreateTime, uReqDTO.getUpdateStartDateTime())
                            .lt(AdminUserDO::getCreateTime, uReqDTO.getUpdateEndDateTime())
                            .or()
                            .ge(AdminUserDO::getUpdateTime, uReqDTO.getUpdateStartDateTime())
                            .lt(AdminUserDO::getUpdateTime, uReqDTO.getUpdateEndDateTime())
                );


        return userMapper.selectList(wrapper);
    }


    @Override
    public List<AdminUserDO> queryUserForKeywords(String keywords, boolean isLikeUserName, boolean isLikeGPN, boolean isLikeEmail) {
        if (StringUtils.isBlank(keywords)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<AdminUserDO> wrapper = Wrappers.lambdaQuery(AdminUserDO.class)
                .or(isLikeUserName, w -> w.like(AdminUserDO::getUsername, keywords))
                .or(isLikeGPN, w -> w.like(AdminUserDO::getGpn, keywords))
                .or(isLikeEmail, w -> w.like(AdminUserDO::getBusinessEmail, keywords))
                .last(" limit 200"); //避免模糊查询结果过大，限定200结果，
        return userMapper.selectList(wrapper);
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }


    @Override
    public Long queryCombinationLikeUsersCount(String firstName, String lastName, String gpn, String legalEntity) {
        if (StrUtil.isBlank(firstName) && StrUtil.isBlank(lastName)
                && StrUtil.isBlank(gpn) && StrUtil.isBlank(legalEntity)) {
            return 0L;
        }
        return userMapper.selectCount(getConditionsWrapper(firstName, lastName, gpn, legalEntity));
    }

    @Override
    public List<AdminUserDO> queryCombinationLikeUsers(String firstName, String lastName, String gpn, String legalEntity) {
        if (StrUtil.isBlank(firstName) && StrUtil.isBlank(lastName)
                && StrUtil.isBlank(gpn) && StrUtil.isBlank(legalEntity)) {
            return null;
        }
        //默认返回100条
        LambdaQueryWrapper<AdminUserDO> wrapper = getConditionsWrapper(firstName, lastName, gpn, legalEntity).last("limit 100");
        return userMapper.selectList(wrapper);
    }

    @Override
    public List<UserSimpleRespVO> getUserSimpleRespVOList() {
        // 获用户门列表，只要开启状态的
        List<AdminUserDO> list = this.getUsersByStatus(CommonStatusEnum.ENABLE.getStatus());
        // 排序后，返回给前端
        List<UserSimpleRespVO> respVOS = UserConvert.INSTANCE.convertList04(list);
        return respVOS;
    }

    /*
    ######################【数据同步】#############################

    根据批次号-》存在：说明是重推
        记录表： 修改 并增加同步次数，
        数据表：逻辑删除，在添加
    根据批次号-》不存在：
        记录表：添加
        数据表：添加
    不管同步的数据时新增的或修改数据，同步记录表及数据表都做添加。
     ############################################################
     */

    /**
     * 用户数据同步至临时表
     *
     * @param userSyncFullDataReqDTO
     * @return
     */
    @Transactional
    @Override
    public void userSyncToTemp(UserSyncFullDataReqDTO userSyncFullDataReqDTO) {

        if (userSyncFullDataReqDTO.getUsers() == null || userSyncFullDataReqDTO.getUsers().size() == 0) {
            //同步数据不能为空
            throw exception(SYNC_USERS_EMPTY);
        }

        String batchNo = userSyncFullDataReqDTO.getBatchNo();
        DataSyncRecordDO dataSyncRecordDO = dataSyncRecordMapper.selectOne(DataSyncRecordDO::getBatchCode, batchNo);

        //批次号不存在，做添加
        if (dataSyncRecordDO == null) {
            SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
            filter.getExcludes().add(DataSyncConstans.JSON_EXCLUDES_USERS);//排除数据只记录参数,第一次数据太多
            String result = JSON.toJSONString(userSyncFullDataReqDTO, filter, JSONWriter.Feature.WriteMapNullValue);
            /*  String result = JSON.toJSONString(userSyncFullDataReqDTO, JSONWriter.Feature.WriteMapNullValue);*/
            // 添加同步记录表
            dataSyncRecordDO = DataSyncRecordDO.builder()
                    .batchCode(batchNo)
                    .syncBizType(SyncBizTypeEnum.USER.getCode())
                    .syncDirection(SyncDirectionEnum.PUSH.getCode())
                    .syncStatus(SyncStatusEnum.SYNC_SUCCESS.getCode())
                    .syncResult(result)
                    .syncNum(0)
                    .source(SyncSourceEnum.HR.getCode())
                    .target(DataSyncConstans.SYSTEM_USERS_SYNC_TEMP)
                    .build();
            dataSyncRecordMapper.insert(dataSyncRecordDO);

        } else {
            //记录表：存在则做增加重推送次数
            Integer syncNum = dataSyncRecordDO.getSyncNum();
            dataSyncRecordDO.setSyncNum(syncNum + 1);
            dataSyncRecordMapper.updateById(dataSyncRecordDO);
            //数据表：根据【批次号】逻辑删除->再添加
            LambdaQueryWrapper<UserSyncTempDO> query = Wrappers.lambdaQuery(UserSyncTempDO.class);
            query.eq(UserSyncTempDO::getBatchNo, batchNo);
            userSyncTempMapper.delete(query);

        }

        //添加同步数据表
        List<UserSyncTempDO> userSyncTempDOS = UserConvert.INSTANCE.
                convertUserSyncTempDOList(userSyncFullDataReqDTO.getUsers());
        userSyncTempDOS.forEach(user -> {
            user.setBatchNo(batchNo);
            user.setHandleAfterSyncStatus(UserSyncHandleStatusEnum.UNPROCESSED_DEFAULT.getCode());
            user.setHandleCodeBlockStatus(UserSyncHandleStatusEnum.UNPROCESSED_DEFAULT.getCode());
            user.setHandleNum(0);
        });
        userSyncTempMapper.insertBatch(userSyncTempDOS);
    }

    @Override
    public List<AdminUserDO> getUserForGpns(Collection<String> gpns) {
        LambdaQueryWrapper<AdminUserDO> wrapper = Wrappers.lambdaQuery(AdminUserDO.class)
                .in(AdminUserDO::getGpn, gpns);
        return  this.list(wrapper);
    }

    private LambdaQueryWrapper<AdminUserDO> getConditionsWrapper(String firstName, String lastName, String gpn, String legalEntity) {
        return Wrappers.lambdaQuery(AdminUserDO.class)
                .eq(StrUtil.isNotBlank(gpn), AdminUserDO::getGpn, gpn)
                .eq(StrUtil.isNotBlank(legalEntity), AdminUserDO::getLegalEntity, legalEntity)
                .and(StrUtil.isNotBlank(firstName) || StrUtil.isNotBlank(lastName),
                        //en|cn ：firstName、lastName
                        wp -> wp.or(StrUtil.isNotBlank(firstName), wap -> wap.like(StrUtil.isNotBlank(firstName), AdminUserDO::getEnFirstName, firstName))
                                .or(StrUtil.isNotBlank(firstName), wap -> wap.like(StrUtil.isNotBlank(firstName), AdminUserDO::getCnFirstName, firstName))
                                .or(StrUtil.isNotBlank(lastName), wap -> wap.like(StrUtil.isNotBlank(lastName), AdminUserDO::getEnLastName, lastName))
                                .or(StrUtil.isNotBlank(lastName), wap -> wap.like(StrUtil.isNotBlank(lastName), AdminUserDO::getCnLastName, lastName))
                );
    }

}
