/*
 * Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yifu.cloud.plus.v1.yifu.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.plugin.excel.vo.ErrorMessage;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserDTO;
import com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserInfo;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.*;
import com.yifu.cloud.plus.v1.yifu.admin.api.util.ParamResolver;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.*;
import com.yifu.cloud.plus.v1.yifu.admin.mapper.*;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysMenuService;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysUserDeptPermissionService;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysUserService;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainListVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.enums.MenuTypeEnum;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.ErrorCodes;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.MsgUtils;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.util.RedisUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.PermissionDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.ldap.entity.PersonVo;
import com.yifu.cloud.plus.v1.yifu.common.ldap.util.LdapUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;

import javax.servlet.http.HttpServletRequest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * @author lengleng
 * @date 2019/2/1
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

	private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

	private final SysRoleMapper sysRoleMapper;

	private final SysDeptMapper sysDeptMapper;

	private final SysMenuService sysMenuService;

	private final SysPostMapper sysPostMapper;

	private final SysUserRoleMapper sysUserRoleMapper;

	private final LdapUtil ldapUtil;

	private final RedisUtil redisUtil;

	private final ArchivesDaprUtil archivesDaprUtil;

	private final PermissionDaprUtil permissionDaprUtil;

	private final SysUserDeptPermissionService userDeptPermissionService;

	@Value("${hrms.id}")
	private String hcmId;

	@Value("${hrms.secret}")
	private String hcmSecret;

	/**
	 * 保存用户信息
	 * @param userDto DTO 对象
	 * @return success/fail
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveUser(UserDTO userDto) {
		SysUser sysUser = new SysUser();
		BeanUtils.copyProperties(userDto, sysUser);
		sysUser.setDelFlag(CommonConstants.STATUS_NORMAL);
		sysUser.setPassword(ENCODER.encode(userDto.getPassword()));
		initDeptName(sysUser);
		baseMapper.insert(sysUser);
		userDto.getRole().stream().map(roleId -> {
			SysUserRole userRole = new SysUserRole();
			userRole.setUserId(sysUser.getUserId());
			userRole.setRoleId(roleId);
			return userRole;
		}).forEach(sysUserRoleMapper::insert);
		return Boolean.TRUE;
	}

	private void initDeptName(SysUser sysUser) {
		if (Common.isNotNull(sysUser.getDeptId())){
			SysDept sysDept = sysDeptMapper.selectById(sysUser.getDeptId());
			if (Common.isNotNull(sysDept)) {
				sysUser.setDeptName(sysDept.getName());
			}
		}
	}

	/**
	 * 通过查用户的全部信息
	 * @param sysUser 用户
	 * @return
	 */
	@Override
	public UserInfo getUserInfo(SysUser sysUser) {
		// LDAP用户处理
		UserInfo userInfo = new UserInfo();
		userInfo.setSysUser(sysUser);
		// 设置角色列表
		List<SysRole> roleList = sysRoleMapper.listRolesByUserId(sysUser.getUserId());
		userInfo.setRoleList(roleList);
		// 设置角色列表 （ID）
		List<Long> roleIds = roleList.stream().map(SysRole::getRoleId).collect(Collectors.toList());
		userInfo.setRoles(ArrayUtil.toArray(roleIds, Long.class));
		// 设置岗位列表
		List<SysPost> postList = sysPostMapper.listPostsByUserId(sysUser.getUserId());
		userInfo.setPostList(postList);
		// 设置权限列表（menu.permission）
		Set<String> permissions = roleIds.stream().map(sysMenuService::findMenuByRoleId).flatMap(Collection::stream)
				.filter(m -> MenuTypeEnum.BUTTON.getType().equals(m.getType())).map(SysMenu::getPermission)
				.filter(StrUtil::isNotBlank).collect(Collectors.toSet());
		userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
		//设置角色列表  （ID）
		List<SysRole> roles = sysRoleMapper.listRolesByUserId(sysUser.getUserId());
		Map<String, List<Long>> clientRoleMap = new HashMap<>();
		if (Common.isNotNull(roles)){
			roles.forEach(role -> {
						if (null != clientRoleMap.get(role.getClientId())) {
							clientRoleMap.get(role.getClientId()).add(role.getRoleId());
						} else {
							clientRoleMap.put(role.getClientId(), Stream.of(role.getRoleId()).collect(toList()));
						}
					}
			);
		}
		// 结算主体权限
		R< TSettleDomainListVo >  sdRes = null;
		if (CommonConstants.TWO_STRING.equals(sysUser.getType())){
			sdRes = archivesDaprUtil.getSettlePermissionForB(sysUser.getUserId());
		}else {
			sdRes = archivesDaprUtil.getPermissionByUserId(sysUser.getUserId());
		}
		if (Common.isNotNull(sdRes) && Common.isNotNull(sdRes.getData())){
			userInfo.setSettleIdList(sdRes.getData().getDeptIds());
		}
		userInfo.setClientRoleMap(clientRoleMap);
		// 客户服务平台的项目权限及对应项目的数据权限
		userInfo.setCspPermMap(userDeptPermissionService.getUserPermission(sysUser.getUserId()));
		return userInfo;
	}
	/**
	 * @Author fxj
	 * @Description LDAP登录验证
	 * @Date 15:01 2023/1/9
	**/
	public void ldapLogin(String username,String password,SysUser user){
		// 如果是LDAP用户 登录LDAP验证并重置密码为用户的正确密码
		if (Common.isNotNull(user) && CommonConstants.ONE_STRING.equals(user.getType())){
			try {
				if (ldapUtil.authenticate(username,password)){
					user.setPassword(ENCODER.encode(password));
				}else {
					// 登录失败，随机密码，保证用户密码不一致
					user = null;
					//user.setPassword(password+RandomUtil.getSix());
					throw  new RuntimeException("LDAP登录失败："+ username);
				}
			} catch (Exception e) {
				log.error("LDAP登录异常",e);
			}
		}
	}
	/**
	 * 分页查询用户信息（含有角色信息）
	 * @param page 分页对象
	 * @param userDTO 参数列表
	 * @return
	 */
	@Override
	public IPage<List<UserVO>> getUserWithRolePage(Page page, UserDTO userDTO) {
		return baseMapper.getUserVosPage(page, userDTO);
	}

	/**
	 * 通过ID查询用户信息
	 * @param id 用户ID
	 * @return 用户信息
	 */
	@Override
	public UserVO getUserVoById(String id) {
		return baseMapper.getUserVoById(id);
	}

	/**
	 * 删除用户
	 * @param sysUser 用户
	 * @return Boolean
	 */
	@Override
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#sysUser.username")
	public Boolean removeUserById(SysUser sysUser) {
		if (null == sysUser || null == sysUser.getUserId()){
			return Boolean.FALSE;
		}
		SysUser user = baseMapper.selectById(sysUser.getUserId());
		if (null == user){
			return Boolean.FALSE;
		}
		String type = "0";
		// 系统内置
		Assert.state(!type.equals(sysUser.getSystemFlag()),
				MsgUtils.getMessage(ErrorCodes.SYS_USER_DELETE_SYSTEM));
		sysUserRoleMapper.deleteByUserId(sysUser.getUserId());
		this.removeById(sysUser.getUserId());
		return Boolean.TRUE;
	}

	@Override
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
	public Boolean updateUserInfo(UserDTO userDto) {
		UserVO userVO = baseMapper.getUserVoByUsername(userDto.getUsername());

		String type = "0";
		// 系统内置
		Assert.state(!type.equals(userDto.getSystemFlag()),
				MsgUtils.getMessage(ErrorCodes.SYS_USER_UPDATE_SYSTEM));

		Assert.isTrue(ENCODER.matches(userDto.getPassword(), userVO.getPassword()),
				MsgUtils.getMessage(ErrorCodes.SYS_USER_UPDATE_PASSWORDERROR));

		SysUser sysUser = new SysUser();
		/*if (StrUtil.isNotBlank(userDto.getNewpassword1())) {
			sysUser.setPassword(ENCODER.encode(userDto.getNewpassword1()));
		}*/
		sysUser.setPhone(userDto.getPhone());
		sysUser.setUserId(userVO.getUserId());
		sysUser.setAvatar(userDto.getAvatar());
		sysUser.setDeptId(userDto.getDeptId());
		initDeptName(sysUser);
		return this.updateById(sysUser);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
	public Boolean updateUser(UserDTO userDto) {

		String userType = "0";
		// 系统内置
		Assert.state(!userType.equals(userDto.getSystemFlag()),
				MsgUtils.getMessage(ErrorCodes.SYS_USER_UPDATE_SYSTEM));

		SysUser sysUser = new SysUser();
		BeanUtils.copyProperties(userDto, sysUser);
		sysUser.setUpdateTime(LocalDateTime.now());
		initDeptName(sysUser);
		/*if (StrUtil.isNotBlank(userDto.getPassword())) {
			sysUser.setPassword(ENCODER.encode(userDto.getPassword()));
		}*/
		this.updateById(sysUser);

		sysUserRoleMapper
				.delete(Wrappers.<SysUserRole>update().lambda().eq(SysUserRole::getUserId, userDto.getUserId()));
		userDto.getRole().forEach(roleId -> {
			SysUserRole userRole = new SysUserRole();
			userRole.setUserId(sysUser.getUserId());
			userRole.setRoleId(roleId);
			userRole.insert();
		});
		return Boolean.TRUE;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#vo.userName")
	public R<String> updatePassword(UserPasswordVo vo) {
		SysUser sysUser = this.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUserId, vo.getUserId()));
		if (ENCODER.matches(vo.getOldPassword(), sysUser.getPassword())) {
			sysUser.setPassword(ENCODER.encode(vo.getNewPassword()));
		} else {
			return R.failed("原密码错误");
		}
		this.updateById(sysUser);
		return R.ok();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#vo.userName")
	public R<String> resetPassword(UserPasswordVo vo) {
		SysUser sysUser = this.getOne(Wrappers.<SysUser>query().lambda()
				.eq(SysUser::getUserId, vo.getUserId())
				.eq(SysUser::getType, CommonConstants.FOUR_STRING));
		if (Common.isNotNull(sysUser)) {
			sysUser.setPassword(ENCODER.encode("123456"));
		}
		this.updateById(sysUser);
		return R.ok();
	}

	/**
	 * 查询上级部门的用户信息
	 * @param username 用户名
	 * @return R
	 */
	@Override
	public List<SysUser> listAncestorUsersByUsername(String username) {
		SysUser sysUser = this.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));

		SysDept sysDept = sysDeptMapper.selectById(sysUser.getDeptId());
		if (sysDept == null) {
			return null;
		}

		Long parentId = sysDept.getParentId();
		return this.list(Wrappers.<SysUser>query().lambda().eq(SysUser::getDeptId, parentId));
	}

	/**
	 * 查询全部的用户
	 * @param userDTO 查询条件
	 * @return list
	 */
	@Override
	public List<UserExcelVO> listUser(UserDTO userDTO) {
		List<UserVO> voList = baseMapper.selectVoList(userDTO);
		// 转换成execl 对象输出
		List<UserExcelVO> userExcelVOList = voList.stream().map(userVO -> {
			UserExcelVO excelVO = new UserExcelVO();
			BeanUtils.copyProperties(userVO, excelVO);
			String roleNameList = userVO.getRoleList().stream().map(SysRole::getRoleName)
					.collect(Collectors.joining(StrUtil.COMMA));
			excelVO.setRoleNameList(roleNameList);
			String postNameList = userVO.getPostList().stream().map(SysPost::getPostName)
					.collect(Collectors.joining(StrUtil.COMMA));
			excelVO.setPostNameList(postNameList);
			return excelVO;
		}).collect(Collectors.toList());
		return userExcelVOList;
	}

	/**
	 * excel 导入用户, 插入正确的 错误的提示行号
	 * @param excelVOList excel 列表数据
	 * @param bindingResult 错误数据
	 * @return ok fail
	 */
	@Override
	public R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult) {
		// 通用校验获取失败的数据
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();

		// 个性化校验逻辑
		List<SysUser> userList = this.list();
		List<SysDept> deptList = sysDeptMapper.selectList(Wrappers.emptyWrapper());
		List<SysRole> roleList = sysRoleMapper.selectList(Wrappers.emptyWrapper());
		List<SysPost> postList = sysPostMapper.selectList(Wrappers.emptyWrapper());

		// 执行数据插入操作 组装 UserDto
		for (int i = 0; i < excelVOList.size(); i++) {
			UserExcelVO excel = excelVOList.get(i);
			Set<String> errorMsg = new HashSet<>();
			// 校验用户名是否存在
			boolean exsitUserName = userList.stream()
					.anyMatch(sysUser -> excel.getUsername().equals(sysUser.getUsername()));

			if (exsitUserName) {
				errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERNAME_EXISTING, excel.getUsername()));
			}

			// 判断输入的部门名称列表是否合法
			Optional<SysDept> deptOptional = deptList.stream()
					.filter(dept -> excel.getDeptName().equals(dept.getName())).findFirst();
			if (!deptOptional.isPresent()) {
				errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_DEPT_DEPTNAME_INEXISTENCE, excel.getDeptName()));
			}

			// 判断输入的角色名称列表是否合法
			List<String> roleNameList = StrUtil.split(excel.getRoleNameList(), StrUtil.COMMA);
			List<SysRole> roleCollList = roleList.stream()
					.filter(role -> roleNameList.stream().anyMatch(name -> role.getRoleName().equals(name)))
					.collect(Collectors.toList());

			if (roleCollList.size() != roleNameList.size()) {
				errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_ROLE_ROLENAME_INEXISTENCE, excel.getRoleNameList()));
			}

			// 判断输入的岗位名称列表是否合法
			List<String> postNameList = StrUtil.split(excel.getPostNameList(), StrUtil.COMMA);
			List<SysPost> postCollList = postList.stream()
					.filter(post -> postNameList.stream().anyMatch(name -> post.getPostName().equals(name)))
					.collect(Collectors.toList());

			if (postCollList.size() != postNameList.size()) {
				errorMsg.add(MsgUtils.getMessage(ErrorCodes.SYS_POST_POSTNAME_INEXISTENCE, excel.getPostNameList()));
			}

			// 数据合法情况
			if (CollUtil.isEmpty(errorMsg)) {
				insertExcelUser(excel, deptOptional, roleCollList, postCollList);
			}
			else {
				// 数据不合法情况
				errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg));
			}

		}

		if (CollUtil.isNotEmpty(errorMessageList)) {
			return R.failed(errorMessageList);
		}
		return R.ok();
	}

	@Override
	public List<Long> listUserIdByDeptIds(Set<Long> deptIds) {
		return this.listObjs(
				Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId).in(SysUser::getDeptId, deptIds),
				Long.class::cast);
	}

	/**
	 * 插入excel User
	 */
	private void insertExcelUser(UserExcelVO excel, Optional<SysDept> deptOptional, List<SysRole> roleCollList,
			List<SysPost> postCollList) {
		UserDTO userDTO = new UserDTO();
		userDTO.setUsername(excel.getUsername());
		userDTO.setPhone(excel.getPhone());
		// 批量导入初始密码为手机号
		userDTO.setPassword(userDTO.getPhone());
		// 根据部门名称查询部门ID
		userDTO.setDeptId(deptOptional.get().getDeptId());
		// 根据角色名称查询角色ID
		List<Long> roleIdList = roleCollList.stream().map(SysRole::getRoleId).collect(Collectors.toList());
		userDTO.setRole(roleIdList);
		// 插入用户
		this.saveUser(userDTO);
	}

	/**
	 * 注册用户 赋予用户默认角色
	 * @param userDto 用户信息
	 * @return success/false
	 */
	@Override
	public R<Boolean> registerUser(UserDTO userDto) {
		// 判断用户名是否存在
		SysUser sysUser = this.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, userDto.getUsername()));
		if (sysUser != null) {
			return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERNAME_EXISTING, userDto.getUsername()));
		}

		// 获取默认角色编码
		String defaultRole = ParamResolver.getStr("USER_DEFAULT_ROLE");
		// 默认角色
		SysRole sysRole = sysRoleMapper
				.selectOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getRoleCode, defaultRole));

		if (sysRole == null) {
			return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_PARAM_CONFIG_ERROR, "USER_DEFAULT_ROLE"));
		}

		userDto.setRole(Collections.singletonList(sysRole.getRoleId()));
		return R.ok(saveUser(userDto));
	}

	/**
	 * 从ldap中获取用户
	 * @return R
	 */
	@Override
	public R<Boolean> updateByLdap() {
		try {
			List<PersonVo> list = ldapUtil.getAllPersons();
			List<PersonVo> updateList = new ArrayList<>();
			List<SysUser> listUser = null;
			if (null != list) {
				listUser = this.list(Wrappers.<SysUser>query().lambda()
						.eq(SysUser::getType, CommonConstants.ZERO_STRING)
						.eq(SysUser::getSystemFlag, CommonConstants.ONE_STRING)
						.eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL));
				List<String> list1 = listUser.stream().map(SysUser::getUsername).collect(Collectors.toList());
				//筛选出不存在的用户重置为不可用
				List<String> list2 = list.stream().map(PersonVo::getUid).collect(Collectors.toList());
				List<String> collect = list1.stream().filter(s -> !list2.contains(s)
				).collect(Collectors.toList());
				if (!collect.isEmpty()) {
					log.error("要重置为不可用的用户列表：" + collect);
					LambdaUpdateWrapper<SysUser> settleUpdate = new LambdaUpdateWrapper<>();
					settleUpdate.in(SysUser::getUsername, collect)
							.set(SysUser::getDelFlag, CommonConstants.ONE_STRING);
					this.update(settleUpdate);
				}

				List<PersonVo> insertList = new ArrayList<>();
				for (PersonVo personVo : list) {
					if (list1.stream().anyMatch(e -> e.equals(personVo.getUid()))) {
						updateList.add(personVo);
					} else {
						//新增用户赋初始密码
						personVo.setPassword(ENCODER.encode(CommonConstants.DEFAULT_PASSWORD));
						insertList.add(personVo);
					}
				}
				if (!updateList.isEmpty()) {
					baseMapper.batchUpdateUser(updateList);
				}
				if (!insertList.isEmpty()) {
					baseMapper.batchInsertUser(insertList);
					//新增用户的初始化角色
					JSONObject jsonObject;
					for (PersonVo personVo :insertList) {
						if (Common.isNotNull(personVo.getRoleIds())) {
							SysUser user = this.getOne(Wrappers.<SysUser>query().lambda().
									eq(SysUser::getUsername, personVo.getUid()).last(CommonConstants.LAST_ONE_SQL));
							jsonObject = JSONObject.parseObject(personVo.getRoleIds());
							//获取mvp用户的角色
							String userRole=jsonObject.get("hro")==null?"":jsonObject.getString("hro");
							if (!userRole.isEmpty()) {
								Common.getList(userRole).stream().map(roleId -> {
									SysUserRole role = new SysUserRole();
									role.setUserId(user.getUserId());
									role.setRoleId(Long.valueOf(roleId));
									return role;
								}).forEach(sysUserRoleMapper::insert);
							}
							//获取ekp用户的角色
							String ekpUserRole=jsonObject.get("ekp")==null?"":jsonObject.getString("ekp");
							if (!ekpUserRole.isEmpty()) {
								for (String roleId : Common.getList(ekpUserRole)) {
									HcmInitRoleInfoVo vo = new HcmInitRoleInfoVo();
									vo.setLoginName(user.getUsername());
									vo.setRoleId(roleId);
									permissionDaprUtil.saveSysUserRole(vo);
								}
							}
						}
					}
				}
			}
			List<SearchResultEntry> entryList = ldapUtil.getAllPersonNamesWithTraditionalWay();
			List<Map<String,Object>> updUserList = new ArrayList<>();
			List<String> userIdOnlines = new ArrayList<>();
			for (SearchResultEntry entry : entryList) {
				String dn = entry.getDN();
				String userId = "";
				if (dn.contains("uid")) {
					userId = dn.substring(4, dn.indexOf(",", 1));
					userIdOnlines.add(userId);
					dn = dn.substring(dn.indexOf(",", 1) + 1);
				}
				List<String> saveDnList = Arrays.asList(dn.split(",")).stream().filter(e -> (e.contains("ou=") && !e.equals("ou=wanxin"))).collect(Collectors.toList());
				String deptName = saveDnList.get(0).replace("ou=", "");
				int size = saveDnList.size();
				if (size == 1) {
					SysDept sysDept = sysDeptMapper.selectDeptDn(dn);
					if (null == sysDept) {
						if (StringUtils.isEmpty(userId)) {
							SysDept ins = sysDeptMapper.selectCountId(Long.valueOf(entry.getAttributeValue("x-ouid")));
							if (Common.isNotNull(ins)) {
								ins.setName(deptName);
								ins.setDeptDn(dn);
								sysDeptMapper.updateDeptById(ins);
							} else {
								SysDept insertSysDept = new SysDept();
								insertSysDept.setName(deptName);
								insertSysDept.setParentId(0L);
								insertSysDept.setDeptDn(dn);
								if (Common.isNotNull(entry.getAttributeValue("x-ouid"))) {
									insertSysDept.setDeptId(Long.valueOf(entry.getAttributeValue("x-ouid")));
								}
								insertSysDept.setDelFlag(CommonConstants.ZERO_STRING);
								sysDeptMapper.insert(insertSysDept);
							}
						}
					} else {
						sysDept.setName(deptName);
						sysDeptMapper.updateDeptById(sysDept);
					}
				} else {
					SysDept sysDept = sysDeptMapper.selectDeptDn(dn.substring(dn.indexOf("ou=", 2), dn.length()));
					if (null != sysDept) {
						SysDept sysDeptCount = sysDeptMapper.selectDeptDn(dn);
						if (null == sysDeptCount) {
							if (StringUtils.isEmpty(userId)) {
								SysDept ins = sysDeptMapper.selectCountId(Long.valueOf(entry.getAttributeValue("x-ouid")));
								if (Common.isNotNull(ins)) {
									ins.setName(deptName);
									ins.setDeptDn(dn);
									ins.setParentId(sysDept.getDeptId());
									sysDeptMapper.updateDeptById(ins);
								} else {
									SysDept insertSysDept = new SysDept();
									insertSysDept.setName(deptName);
									insertSysDept.setParentId(sysDept.getDeptId());
									insertSysDept.setDeptDn(dn);
									if (Common.isNotNull(entry.getAttributeValue("x-ouid"))) {
										insertSysDept.setDeptId(Long.valueOf(entry.getAttributeValue("x-ouid")));
									}
									insertSysDept.setDelFlag(CommonConstants.ZERO_STRING);
									sysDeptMapper.insert(insertSysDept);
								}
							}
						} else {
							if (!StringUtils.isEmpty(userId)) {
								Map<String,Object> map = new HashMap<>();
								map.put("userId",userId);
								map.put("deptId",sysDeptCount.getDeptId());
								map.put("deptName",deptName);
								updUserList.add(map);
							}else {
								sysDeptCount.setName(deptName);
								sysDeptCount.setDeptDn(dn);
								sysDeptCount.setParentId(sysDept.getDeptId());
								sysDeptMapper.updateDeptById(sysDeptCount);
							}
						}
					}
				}
			}
			//更新用户信息
			if (!updUserList.isEmpty()) {
				baseMapper.updateUser(updUserList);
			}
			// 对比 updateList 和 updUserList 的 userId  如果 updateList 中存在 但是updUserList 中不存在 则更新成非在用
			List<String> updateListStr = updateList.stream().map(e -> e.getUid()).collect(Collectors.toList());
			List<String> updateUserList = updateListStr.stream().filter(e -> !userIdOnlines.stream().anyMatch(f -> f.equals(e))).collect(Collectors.toList());
			if (!userIdOnlines.isEmpty()){
				LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper();
				wrapper.in(SysUser::getUsername, userIdOnlines);
				wrapper.set(SysUser::getLockFlag, CommonConstants.ZERO_STRING);
				this.update(wrapper);
			}
			if (!updateUserList.isEmpty()) {
				LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper();
				wrapper.in(SysUser::getUsername, updateUserList);
				wrapper.set(SysUser::getLockFlag, CommonConstants.NINE_STRING);
				this.update(wrapper);
			}
			// 刷新用户缓存
			Map<String, String> existMap = listUser.stream().collect(Collectors.toMap(SysUser::getUsername,SysUser::getLockFlag));
			List<String> refreshList = new ArrayList<>();
			if (Common.isNotNull(existMap)){
				//找出启用锁定的数据
				if (!userIdOnlines.isEmpty()){
					for (String userName : userIdOnlines){
						if (existMap.containsKey(userName)){
							if (!CommonConstants.ZERO_STRING.equals(existMap.get(userName))){
								refreshList.add(userName);
							}
						}
					}
				}
				//找出锁定启用的数据
				if (!updateUserList.isEmpty()){
					for (String userName : updateUserList){
						if (existMap.containsKey(userName)){
							if (!CommonConstants.NINE_STRING.equals(existMap.get(userName))){
								refreshList.add(userName);
							}
						}
					}
				}
				// 清理缓存
				if (!refreshList.isEmpty()){
					for (String userName : refreshList){
						redisUtil.remove(CacheConstants.USER_DETAILS +"::"+ userName);
					}
				}
			}



		}catch (Exception e) {
			log.info("用户部门信息同步异常：" + e.getMessage());
			return R.failed("用户部门信息同步异常！");
		}
		return R.ok();
	}

	/**
	 * 从ldap中验证登录用户
	 * @return R
	 */
	@Override
	public R<Boolean> loginAuthentication(String userName, String password) throws NoSuchAlgorithmException {
		if (Boolean.TRUE.equals(ldapUtil.authenticate(userName,password))) {
			return R.ok();
		}
		return R.failed("验证不通过");
	}

	/**
	 * @param empIdCard 身份证
	 * @param empName 姓名
	 * @param empPhone 手机号
	 * @param openId 微信的openId，工资条使用的
	 * @param headImgUrl 头像
	 * @Param nickName  微信昵称
	 * @Description: 保存C端用户
	 * @Author: hgw
	 * @Date: 2022/12/13 11:54
	 * @return: boolean
	 **/
	@Override
	public boolean saveCUser(String empIdCard, String empName, String empPhone, String openId, String headImgUrl,String nickName) {
		SysUser user = this.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, empIdCard)
				.eq(SysUser::getDelFlag, CommonConstants.ZERO_STRING).last(CommonConstants.LAST_ONE_SQL));
		//用户信息封装
		if (user == null) {
 			user = new SysUser();
			user.setPassword(ENCODER.encode("123456"));
			user.setUsername(empIdCard);
			user.setNickname(empName);
			user.setPost("C端用户");
			user.setLockFlag(CommonConstants.STATUS_NORMAL);
			user.setDelFlag(CommonConstants.STATUS_NORMAL);
			user.setCreateTime(LocalDateTime.now());
			user.setPhone(empPhone);
			//使用根节点
			user.setDeptId(CommonConstants.WX_C_ORG_ID);
			user.setDeptName(CommonConstants.WX_C_ORG_NAME);
			user.setUserGroup(CommonConstants.ONE_STRING);
			user.setEmail(empPhone+"@193.com");
			user.setSystemFlag(CommonConstants.ONE_STRING);
			user.setAvatar(headImgUrl);
		} else {
			user.setUpdateTime(LocalDateTime.now());
			user.setUpdateBy("C端");
		}
		user.setType(CommonConstants.THREE_STRING);
		user.setWxOpenid(openId);
		user.setWxNickName(nickName);
		return this.saveOrUpdate(user);
	}
	@Override
	public Page<BusinessUserVo> getBusinessUserVoPage(Page page, BusinessUserVo user) {
		if (Common.isNotNull(user.getOrganIdB()) || Common.isNotNull(user.getOrganLevelB())){
			R<List<String>> userIdR = null;//remoteBusinessService.getUserIdByOrganInfo(user.getOrganIdB(), user.getOrganLevelB(), SecurityConstants.FROM_IN);
			if (null != userIdR && Common.isNotNull(userIdR.getData())){
				user.setUserIdsB(userIdR.getData());
			}
		}
		return baseMapper.getBusinessUserVoPage(page,user);
	}
	/**
	 * 更新用户锁定状态
	 *
	 * @param user
	 * @param lockFlag
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	//不用原因user.phone和user.wxUserId做键时可能为空 服务报错
	public Boolean updateLockFlagById(SysUser user, String lockFlag) {
		clenrUserCache(user.getUsername(),null,user.getPhone());
		SysUser sysUser = new SysUser();
		sysUser.setUserId(user.getUserId());
		sysUser.setLockFlag(lockFlag);
		return this.updateById(sysUser);
	}

	/**
	 * 从ldap实时更新用户和部门
	 * @return R
	 */
	@Override
	public R<String> updateUserAndDept(HttpServletRequest request,JSONObject json) {
		//权限验证
		String appId = request.getHeader("HRBS-APP-ID");
		String appSecret = request.getHeader("HRBS-APP-SECRET");
		if(Common.isEmpty(appId) || Common.isEmpty(appSecret)){
			return new R<>("操作失败，权限标识错误！", 500);
		}
		if(!hcmId.equals(appId) || !hcmSecret.equals(appSecret) ){
			return new R<>("操作失败，无权限！", 500);
		}
		if(Common.isEmpty(json)) {
			return new R<>("传参不能为空", 500);
		}
		boolean isAll = (boolean) json.get("isAll");
		String dataType = json.get("dataType").toString();
		//获取人员和部门信息
		JSONArray updateParamsArr=json.getJSONArray("data");
		//全量更新直接调用定时任务接口
		if (isAll) {
			this.updateByLdap();
			//用户同步操作
		} else if ("user".equals(dataType)) {
			//更新或者新增用户信息
			updateOrSaveUser(updateParamsArr);
		} else {
			//更新或者新增部门信息
			updateOrSaveDept(updateParamsArr);
		}
		return new R<>("同步成功！", 200);
	}

	/**
	 * 更新或者新增用户信息
	 * @return
	 */
	private void updateOrSaveUser(JSONArray updateParamsArr) {
		List<SysUser> listUser = this.list(Wrappers.<SysUser>query().lambda()
				.eq(SysUser::getType, CommonConstants.STATUS_NORMAL)
				.eq(SysUser::getDelFlag, CommonConstants.STATUS_NORMAL));
		List<String> list1 = listUser.stream().map(SysUser::getUsername).collect(Collectors.toList());
		List<PersonVo> updateList = new ArrayList<>();
		List<PersonVo> insertList = new ArrayList<>();
		SysDept sysDeptCount;
		List<String> saveDnList;
		JSONObject updateJson;
		for (int i = 0; i < updateParamsArr.size(); i++) {
			updateJson=updateParamsArr.getJSONObject(i);
			PersonVo personVo = new PersonVo();
			personVo.setUid(updateJson.get("uid")==null?"":updateJson.getString("uid"));
			personVo.setPersonName(updateJson.get("cn")==null?"":updateJson.getString("cn"));
			personVo.setTelephoneNumber(updateJson.get("telephoneNumber")==null?"":updateJson.getString("telephoneNumber"));
			personVo.setEmail(updateJson.get("mail")==null?"":updateJson.getString("mail"));
			personVo.setRoleIds(updateJson.get("x-init-role-ids")==null?"":updateJson.getString("x-init-role-ids"));
			String dn = updateJson.get("dn")==null?"":updateJson.getString("dn");
			log.info("更新人员信息：" + dn + "_" +personVo.getUid());
			if (dn.contains("uid")) {
				dn = dn.substring(dn.indexOf(",", 1) + 1);
			}
			saveDnList = Arrays.stream(dn.split(",")).filter(e -> (e.contains("ou=") && !e.equals("ou=wanxin"))).collect(Collectors.toList());
			String deptName = saveDnList.get(0).replace("ou=", "");
			personVo.setDeptName(deptName);
			sysDeptCount = sysDeptMapper.selectDeptDn(dn);
			if (Common.isEmpty(sysDeptCount)) {
				continue;
			} else {
				personVo.setDeptName(deptName);
				personVo.setDeptId(sysDeptCount.getDeptId());
			}
			if (list1.stream().anyMatch(e -> e.equals(personVo.getUid()))) {
				updateList.add(personVo);
			} else {
				//新增用户赋初始密码
				personVo.setPassword(ENCODER.encode(CommonConstants.DEFAULT_PASSWORD));
				insertList.add(personVo);
			}
		}
		if (!updateList.isEmpty()) {
			baseMapper.batchUpdateUser(updateList);
		}
		if (!insertList.isEmpty()) {
			baseMapper.batchInsertUser(insertList);
			//新增用户的初始化角色
			JSONObject jsonObject;
			for (PersonVo personVo :insertList) {
				if (Common.isNotNull(personVo.getRoleIds())) {
					SysUser user = this.getOne(Wrappers.<SysUser>query().lambda().
							eq(SysUser::getUsername, personVo.getUid()).last(CommonConstants.LAST_ONE_SQL));
					jsonObject = JSONObject.parseObject(personVo.getRoleIds());
					//获取mvp用户的角色
					String userRole=jsonObject.get("hro")==null?"":jsonObject.getString("hro");
					if (!userRole.isEmpty()) {
						Common.getList(userRole).stream().map(roleId -> {
							SysUserRole role = new SysUserRole();
							role.setUserId(user.getUserId());
							role.setRoleId(Long.valueOf(roleId));
							return role;
						}).forEach(sysUserRoleMapper::insert);
					}
					//获取ekp用户的角色
					String ekpUserRole=jsonObject.get("ekp")==null?"":jsonObject.getString("ekp");
					if (!ekpUserRole.isEmpty()) {
						for (String roleId : Common.getList(ekpUserRole)) {
							HcmInitRoleInfoVo vo = new HcmInitRoleInfoVo();
							vo.setLoginName(user.getUsername());
							vo.setRoleId(roleId);
							permissionDaprUtil.saveSysUserRole(vo);
						}
					}
				}
			}
		}
	}

	/**
	 * 更新或者新增部门信息
	 * @return
	 */
	private void updateOrSaveDept(JSONArray updateParamsArr) {
		SysDept sysDeptCount;
		List<String> saveDnList;
		JSONObject updateJson;
		for (int i = 0; i < updateParamsArr.size(); i++) {
			updateJson = updateParamsArr.getJSONObject(i);
			String dn = updateJson.get("dn")==null?"":updateJson.getString("dn");
			String deptId = updateJson.get("x-ouid")==null?"":updateJson.getString("x-ouid");
			String deptName = updateJson.get("ou")==null?"":updateJson.getString("ou");
			log.info("更新部门信息：" + dn);
			saveDnList = Arrays.stream(dn.split(",")).filter(e -> (e.contains("ou=") && !e.equals("ou=wanxin"))).collect(Collectors.toList());
			int size = saveDnList.size();
			if (size == 1) {
				SysDept sysDept = sysDeptMapper.selectDeptDn(dn);
				if (null == sysDept) {
					SysDept ins = sysDeptMapper.selectCountId(Long.valueOf(deptId));
					if (Common.isNotNull(ins)) {
						ins.setName(deptName);
						ins.setDeptDn(dn);
						sysDeptMapper.updateDeptById(ins);
					} else {
						SysDept insertSysDept = new SysDept();
						insertSysDept.setName(deptName);
						insertSysDept.setParentId(0L);
						insertSysDept.setDeptDn(dn);
						if (Common.isNotNull(deptId)) {
							insertSysDept.setDeptId(Long.valueOf(deptId));
						}
						insertSysDept.setDelFlag(CommonConstants.ZERO_STRING);
						sysDeptMapper.insert(insertSysDept);
					}
				} else {
					sysDept.setName(deptName);
					sysDeptMapper.updateDeptById(sysDept);
				}
			} else {
				SysDept sysDept = sysDeptMapper.selectDeptDn(dn.substring(dn.indexOf("ou=", 2), dn.length()));
				if (null != sysDept) {
					sysDeptCount = sysDeptMapper.selectDeptDn(dn);
					if (null == sysDeptCount) {
						SysDept ins = sysDeptMapper.selectCountId(Long.valueOf(deptId));
						if (Common.isNotNull(ins)) {
							ins.setName(deptName);
							ins.setDeptDn(dn);
							ins.setParentId(sysDept.getDeptId());
							sysDeptMapper.updateDeptById(ins);
						} else {
							SysDept insertSysDept = new SysDept();
							insertSysDept.setName(deptName);
							insertSysDept.setParentId(sysDept.getDeptId());
							insertSysDept.setDeptDn(dn);
							if (Common.isNotNull(deptId)) {
								insertSysDept.setDeptId(Long.valueOf(deptId));
							}
							insertSysDept.setDelFlag(CommonConstants.ZERO_STRING);
							sysDeptMapper.insert(insertSysDept);
						}
					} else {
						sysDeptCount.setName(deptName);
						sysDeptCount.setDeptDn(dn);
						sysDeptCount.setParentId(sysDept.getDeptId());
						sysDeptMapper.updateDeptById(sysDeptCount);
					}
				}
			}
		}

	}

	private void clenrUserCache(String username,String wxUserId,String phone){
		//用户名登录用户缓存清除
		if(Common.isNotNull(username)){
			redisUtil.remove(CacheConstants.USER_DETAILS +"::"+username);
		}
		//微信登录用户缓存清除
		if(Common.isNotNull(wxUserId)){
			redisUtil.remove(CacheConstants.USER_DETAILS + "_wx::"+wxUserId);
		}
		//手机号登录用户缓存清除
		if(Common.isNotNull(phone)){
			redisUtil.remove(CacheConstants.USER_DETAILS + "_phone::"+phone);
		}
	}

	@Override
	public List<SysUser> getUserByRoleIdForCrm(Integer departId, String roleId) {
		return baseMapper.getUserByRoleIdForCrm(departId,roleId);
	}

	@Override
	public List<SysUser> getUserManagerByUpDepartIdUp(Integer departId, String roleId) {
		return baseMapper.getUserManagerByUpDepartIdUp(departId,roleId);
	}

	@Override
	public Boolean selectExitDeptCompany(String deptId) {
		String dn = baseMapper.selectExitDeptCompany(deptId);
		if (Common.isEmpty(dn)) {
			return false;
		}
		List<String> deptList = CommonConstants.deptList;
		return deptList.stream().anyMatch(dn::contains);
	}

	/**
	 * 分页查询系统里所有用户
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 *
	 * @author chenyuxi
	 * @since 1.9.7
	 */
	@Override
	public IPage<SysUser> getAllUserPage(Page page, UserDTO userDTO) {
		if(Common.isEmpty(userDTO.getNameOrPhone())){
			return baseMapper.getAllUserPage(page, userDTO);
		}
		return baseMapper.getAllUserPageWhere(page, userDTO);
	}

	@Override
	public R<IPage<SysUser>>  cspUserPage(Page page, String deptId, String userName, String nickName) {
		if (Common.isEmpty(deptId)){
			return R.failed(null,CommonConstants.PARAM_IS_NOT_ERROR);
		}
		SysDept dept = sysDeptMapper.selectOne(Wrappers.<SysDept>query().lambda()
				.eq(SysDept::getDeptId,deptId).last(CommonConstants.LAST_ONE_SQL));
		if (Common.isEmpty(dept)){
			return  R.failed(null,CommonConstants.PARAM_IS_NOT_ERROR);
		}
		return R.ok(baseMapper.cspUserPage(page,deptId,userName,nickName,dept.getProjectNo()));
	}

	@Override
	public SysCspDeptVo selectCspDeptByUserDeptId(SysCspDeptVo vo) {
		SysCspDeptVo returnVo = userDeptPermissionService.selectCasDeptVo(vo.getUserId(),vo.getProjectId());
		if (Common.isNotNull(returnVo) && Common.isNotNull(returnVo.getDepartName()) && Common.isNotNull(returnVo.getDepartId())) {
			vo.setDepartName(returnVo.getDepartName());
			vo.setDepartId(returnVo.getDepartId());
		} else {
			return null;
		}
		return vo;
	}

	/**
	 * @Description: 判断用户的角色是否有菜单
	 * @Author: hgw
	 * @Date: 2025/9/5 10:01
	 * @return: com.yifu.cloud.plus.v1.yifu.admin.api.vo.KeyValueReturnVo
	 **/
	@Override
	public KeyValueReturnVo judgeDispatchAudit(ListAndStringVo paramVo) {
		List<String> idList = paramVo.getIdList();
		// 派单审核 menuId = "1549677464986763265"
		String menuId = paramVo.getIdString();
		KeyValueReturnVo vo = new KeyValueReturnVo();
		if (idList == null || idList.isEmpty() || Common.isEmpty(menuId)) {
			return vo;
		}
		List<KeyValueVo> voList = baseMapper.judgeMenuByUserId(idList, menuId);
		return getKeyValueReturnVo(vo, voList);
	}

	/**
	 * @Description: 判断用户的权限（用户拼接用户组）是否有菜单
	 * @Author: hgw
	 * @Date: 2025/9/5 10:01
	 * @return: com.yifu.cloud.plus.v1.yifu.admin.api.vo.KeyValueReturnVo
	 **/
	@Override
	public KeyValueReturnVo judgeDiyAuthMenuByUserId(ListAndStringVo paramVo) {
		List<String> idList = paramVo.getIdList();
		// 派单审核 menuId = "1549677464986763265"
		String menuId = paramVo.getIdString();
		KeyValueReturnVo vo = new KeyValueReturnVo();
		if (idList == null || idList.isEmpty() || Common.isEmpty(menuId)) {
			return vo;
		}
		List<KeyValueVo> voList = baseMapper.judgeDiyAuthMenuByUserId(idList, menuId);
		return getKeyValueReturnVo(vo, voList);
	}

	private KeyValueReturnVo getKeyValueReturnVo(KeyValueReturnVo vo, List<KeyValueVo> voList) {
		if (voList != null && !voList.isEmpty()) {
			Map<String, String> map = new HashMap<>();
			for (KeyValueVo keyValueVo : voList) {
				map.put(keyValueVo.getKeyStr(), keyValueVo.getValueStr());
			}
			vo.setKeyValueMap( map);
		}
		return vo;
	}


}
