/*
 *
 *      Copyright (c) 2018-2025, hnqz All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: hnqz
 *
 */

package com.qunzhixinxi.hnqz.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.Md5Utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.qunzhixinxi.hnqz.admin.api.dto.UserDTO;
import com.qunzhixinxi.hnqz.admin.api.dto.UserInfo;
import com.qunzhixinxi.hnqz.admin.api.dto.UserPwd;
import com.qunzhixinxi.hnqz.admin.api.entity.*;
import com.qunzhixinxi.hnqz.admin.api.vo.MenuVO;
import com.qunzhixinxi.hnqz.admin.api.vo.UserVO;
import com.qunzhixinxi.hnqz.admin.entity.SysCertResultRecord;
import com.qunzhixinxi.hnqz.admin.entity.SysDeptSub;
import com.qunzhixinxi.hnqz.admin.entity.dto.CommonUserDTO;
import com.qunzhixinxi.hnqz.admin.entity.input.UserCertificationInput;
import com.qunzhixinxi.hnqz.admin.entity.output.UserCertificationOutput;
import com.qunzhixinxi.hnqz.admin.enums.DelEnum;
import com.qunzhixinxi.hnqz.admin.enums.LockEnum;
import com.qunzhixinxi.hnqz.admin.enums.SubjectTypeEnum;
import com.qunzhixinxi.hnqz.admin.mapper.*;
import com.qunzhixinxi.hnqz.admin.service.*;
import com.qunzhixinxi.hnqz.common.core.constant.CacheConstants;
import com.qunzhixinxi.hnqz.common.core.constant.CommonConstants;
import com.qunzhixinxi.hnqz.common.core.util.R;
import com.qunzhixinxi.hnqz.common.data.datascope.DataScope;
import com.qunzhixinxi.hnqz.common.ding.config.DingConfig;
import com.qunzhixinxi.hnqz.common.ding.entity.EmployCheckResponse;
import com.qunzhixinxi.hnqz.common.ding.entity.EmployCheckResultItem;
import com.qunzhixinxi.hnqz.common.ding.enums.DingEnum;
import com.qunzhixinxi.hnqz.common.ding.service.DingService;
import com.qunzhixinxi.hnqz.common.security.service.HnqzUser;
import com.qunzhixinxi.hnqz.common.security.util.SecurityUtils;
import com.qunzhixinxi.hnqz.common.taxhelper.config.TaxHelperConfig;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.TaxHelperAddMemberModel;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.request.TaxHelperAddMemberRequest;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.response.TaxHelperResponse;
import com.qunzhixinxi.hnqz.common.taxhelper.enums.TaxHelperCertStatus;
import com.qunzhixinxi.hnqz.common.taxhelper.service.TaxHelperService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
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 java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hnqz
 * @date 2017/10/31
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

	private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

	private final SysMenuService sysMenuService;

	private final SysRoleService sysRoleService;

	private final SysDeptService sysDeptService;

	private final SysUserRoleService sysUserRoleService;

	private final SysUserRoleMapper sysUserRoleMapper;

	private final SysUserMapper sysUserMapper;

	private final SysDeptRelationService sysDeptRelationService;

	private final SysDeptRelationMapper sysDeptRelationMapper;

	private final RedisTemplate redisTemplate;

	private final DingService dingService;

	private final SysDeptSubMapper sysDeptSubMapper;

	private final TaxHelperService taxHelperService;

	private final WmDaAgentMapper wmDaAgentMapper;

	private final WmDaDrugEntMapper wmDaDrugEntMapper;

	private final SysCertResultRecordMapper sysCertResultRecordMapper;

	/**
	 * @Modify: start
	 * @Version: v2021.4.16
	 * @Author: ryz
	 * @Date: 2021/5/6
	 */
	@Override
	public R getAuthInfo(UserCertificationInput input) {

		SysUser sysUser = sysUserMapper.selectById(input.getUserId());

		SysDeptSub sysDeptSub = new SysDeptSub();
//		sysDeptSub.setDeptId(SecurityUtils.getUser().getDeptId());
		sysDeptSub.setDeptId(sysUser.getDeptId());
		sysDeptSub.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		List<SysDeptSub> subList = sysDeptSubMapper.selectList(Wrappers.query(sysDeptSub));
		UserCertificationOutput output = new UserCertificationOutput();
		output.setSubList(subList);
		output.setUserInfo(sysUser);
		return R.ok(output);
	}

	/**
	 * 通过excel批量创建用户
	 *
	 * @param commonUserDTOListMap 通用用户dto
	 * @return 结果
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, String> batchByExcel(Map<String, List<CommonUserDTO>> commonUserDTOListMap) {

		// 变量
		Map<String, String> errorMap = new HashMap<>();
		List<UserDTO> currentList = new ArrayList<>();

		// 获取操作员
		HnqzUser creator = SecurityUtils.getUser();

		// 业务值校验
		for (Map.Entry<String, List<CommonUserDTO>> entry : commonUserDTOListMap.entrySet()) {
			checkoutCommonUserDTOInfo(entry.getValue(), creator, errorMap, currentList);
		}

		// 上传结果
		if (CollectionUtil.isEmpty(errorMap)) {
			currentList.forEach(this::saveUser);
		}

		return errorMap;
	}

	/**
	 * 封装错误信息
	 *
	 * @param errorMap 记录错误信息map
	 * @param key      原因
	 * @param idStr    错误id
	 */
	private void errorMap(Map<String, String> errorMap, String key, String idStr) {
		if (errorMap.containsKey(key)) {
			String val = errorMap.get(key);
			idStr = String.join(";", val, idStr);
		}
		errorMap.put(key, idStr);
	}

	/**
	 * 角色校验
	 *
	 * @param roleName 角色名称
	 * @param userDTO 用户dto
	 * @param dept     部门
	 * @return 校验错误信息
	 */
	private String checkoutCommonUserRole(String roleName, UserDTO userDTO, SysDept dept) {

		String errorInfo = null;

		if (StringUtils.isEmpty(roleName)) {
			errorInfo = "角色名称为空";
		} else {
			// 根据角色名称获取角色
			SysRole sysRole = sysRoleService.getOne(Wrappers.<SysRole>lambdaQuery()
					.eq(SysRole::getRoleName, roleName)
					.eq(SysRole::getDelFlag, DelEnum.NOT_DEL.val()));
			if (sysRole == null) {
				errorInfo = "角色不存在或者未启用";
			} else {
				userDTO.setRole(Collections.singletonList(sysRole.getRoleId()));
				if (userDTO.getRole().contains(2)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (r.getRoleId() == 3) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为药企管理员！";
										continue;
									}
									if (r.getRoleId() == 4) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为CSO管理员！";
										continue;
									}
									if (r.getRoleId() == 5) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为全职学术推广员！";
										continue;
									}
									if (r.getRoleId() == 6) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为兼职学术推广员！";
										continue;
									}
									if (r.getRoleId() == 7) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为财务管理员！";
										continue;
									}
								}
							}
						}
					}

				} else if (userDTO.getRole().contains(3)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (r.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在药企管理员角色,不能同时为平台管理员！";
										continue;
									}
									if (r.getRoleId() == 4) {
										errorInfo = errorInfo + "用户已存在药企管理员角色,不能同时为CSO管理员！";
										continue;
									}
									if (dept.getLevel() == 3 || dept.getLevel() == 4) {
										if (r.getRoleId() == 5) {
											errorInfo = errorInfo + "用户已存在CSO关系角色,不能同时为药企管理员！";
											continue;
										}
									}
								}
							}
						}
					}

				} else if (userDTO.getRole().contains(4)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (sysRole.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在平台管理员角色,不能同时为！";
										continue;
									}

									if (r.getRoleId() == 3) {
										errorInfo = errorInfo + "用户已存在药企管理员角色,不能同时为CSO管理员！";
										continue;
									}
									if (r.getRoleId() == 5) {
										SysUserRole sysUserRole = new SysUserRole();
										sysUserRole.setUserId(userVO.getUserId());
										List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectById(sysUserRole);
										for (int k = 0; k < sysUserRoleList.size(); k++) {
											SysUser sysUser = getById(sysUserRoleList.get(k).getUserId());
											if (!sysUser.getDeptId().equals(userDTO.getDeptId())) {
												errorInfo = errorInfo + "用户已存在全职学术推广员角色,不能为其他机构CSO管理员！";
												continue;
											}
										}
									}
								}
							}
						}
					}

				} else if (userDTO.getRole().contains(7)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (r.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在平台管理员,不能同时为财务管理员！";
										continue;
									}
									if (dept.getLevel() == 3 || dept.getLevel() == 4) {
										if (r.getRoleId() == 3) {
											errorInfo = errorInfo + "用户已存在药企管理员,不能同时为CSO机构财务管理员！";
											continue;
										}
									}
								}
							}
						}
					}

				} else if (userDTO.getRole().contains(5)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (r.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在平台管理员,不能同时为全职学术推广员！";
										continue;
									}
									if (r.getRoleId() == 3) {
										if (dept.getLevel() == 3 || dept.getLevel() == 4) {
											errorInfo = errorInfo + "用户已存在药企管理员,不能为CSO的全职学术推广员！";
											continue;
										}
									}
									if (r.getRoleId() == 4) {
										if (dept.getLevel() == 3 || dept.getLevel() == 4) {
											errorInfo = errorInfo + "用户已存在CSO管理员,不能为其他CSO的全职学术推广员！";
											continue;
										}
									}

								}
							}
						}
					}

				} else if (userDTO.getRole().contains(6)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (r.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在平台管理员,不能同时为兼职学术推广员！";
										continue;
									}
									SysUserRole sysUserRole = new SysUserRole();
									sysUserRole.setUserId(userVO.getUserId());
									List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectById(sysUserRole);
									for (int k = 0; k < sysUserRoleList.size(); k++) {
										if (sysUserRoleList.get(k).getRoleId().equals(7)) {
											SysUser sysUser = getById(sysUserRoleList.get(k).getUserId());
											if (sysUser.getDeptId().equals(userDTO.getDeptId())) {
												errorInfo = errorInfo + "用户已存在财务管理员角色，不能同时为兼职学术推广员！";
												continue;
											}
										}
									}
								}
							}
						}
					}

				} else if (userDTO.getRole().contains(9)) {
					UserDTO tmp = new UserDTO();
					tmp.setUsername(userDTO.getUsername());
					tmp.setDelFlag("0");
					List<UserVO> userVoList = sysUserMapper.selectByPhone(tmp);
					if (userVoList.size() > 0) {
						for (UserVO userVO : userVoList) {
							if (null != userVO.getRoleList()) {
								for (SysRole r : userVO.getRoleList()) {
									if (sysRole.getRoleId() == 2) {
										errorInfo = errorInfo + "用户已存在平台管理员,不能同时为CRO管理员！";
										continue;
									}
									if (r.getRoleId() == 3) {
										errorInfo = errorInfo + "用户已存在药企管理员,不能同时为CRO管理员！";
										continue;
									}
								}
							}
						}
					}
				}
				if (userDTO.getRole().contains(3)) {
					if (dept.getLevel() != 2) {
						errorInfo = errorInfo + "角色选为药企管理员时,组织架构必须为药企！";
					}
				}
			}
		}

		return errorInfo;
	}

	/**
	 * 校验通用dto信息
	 *
	 * @param commonUserDTOList 通用用户dto信息
	 * @param creator       创建人
	 * @param errorMap      错误信息记录map
	 * @param currentList   正确结果收集信息
	 */
	private void checkoutCommonUserDTOInfo(List<CommonUserDTO> commonUserDTOList, HnqzUser
			creator, Map<String, String> errorMap, List<UserDTO> currentList) {

		// 行编号
		log.info("开始校验数据：{}", commonUserDTOList);

		if (commonUserDTOList.size() != 1){
			log.error("表中手机号重复");
			Set<String> idSet = commonUserDTOList.stream().map(dto -> dto.getId()).collect(Collectors.toSet());
			errorMap(errorMap, "表中手机号重复", JSONUtil.toJsonStr(idSet));
		}

		CommonUserDTO commonUserDTO = commonUserDTOList.get(0);

		UserDTO userDTO = new UserDTO();

		// 校验用户名称
		String realName = StrUtil.cleanBlank(commonUserDTO.getRealName());
		if (StringUtils.isEmpty(realName)) {
			log.error("用户姓名为空");
			errorMap(errorMap, "用户姓名为空", commonUserDTO.getId());
		} else {
			userDTO.setRealname(realName);
		}

		// 校验手机号
		String username = StrUtil.cleanBlank(commonUserDTO.getUsername());
		if (StringUtils.isEmpty(username)) {
			log.error("手机号为空");
			errorMap(errorMap, "用户手机号为空", commonUserDTO.getId());
		} else {
			// 校验手机号格式
			boolean isMobile = Validator.isMobile(username);
			if (!isMobile) {
				log.error("用户手机号各式不正确");
				errorMap(errorMap, "用户手机号各式不正确", commonUserDTO.getId());
			}

			// 校验部门下是否有启用的用户
			int count = count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, username)
					.eq(SysUser::getDeptId,creator.getDeptId())
					.eq(SysUser::getLockFlag, LockEnum.UN_LOCK.val()).eq(SysUser::getDelFlag, DelEnum.NOT_DEL.val()));
			if (count != 0) {
				log.info("手机号被占用");
				errorMap(errorMap, "手机号被占用", commonUserDTO.getId());
			}

			userDTO.setPlatId(username);
			userDTO.setPhone(username);
			userDTO.setUsername(username);
		}

		// 校验省
		String province = StrUtil.cleanBlank(commonUserDTO.getProvince());
		if (StringUtils.isEmpty(province)) {
			log.error("省份为空");
			errorMap(errorMap, "省份为空", commonUserDTO.getId());
		} else {
			province = "全国".equals(province) ? "" : province;
			userDTO.setProvince(province);

			// 校验城市
			if (StringUtils.isEmpty(province)) {
				userDTO.setCity("");
				userDTO.setProvinceCode("");
				userDTO.setCityCode("");
			} else {
				String provinceCode = StrUtil.cleanBlank(commonUserDTO.getProvinceCode());
				if (StringUtils.isEmpty(provinceCode)){
					log.error("省份编码为空");
					errorMap(errorMap, "省份编码为空", commonUserDTO.getId());
				}
				userDTO.setProvinceCode(provinceCode);

				String city = StrUtil.cleanBlank(commonUserDTO.getCity());
				if (StringUtils.isEmpty(city)) {
					log.error("城市为空");
					errorMap(errorMap, "城市为空", commonUserDTO.getId());
				}

				userDTO.setCity(city);

				String cityCode = StrUtil.cleanBlank(commonUserDTO.getCityCode());
				if (StringUtils.isEmpty(cityCode)){
					log.error("城市编码为空");
					errorMap(errorMap, "城市编码为空", commonUserDTO.getId());
				}
				userDTO.setCityCode(cityCode);

			}
		}

		// 校验用户角色
		SysDept dept = sysDeptService.getById(creator.getDeptId());
		String roleName = StrUtil.cleanBlank(commonUserDTO.getRoleName());
		String errInfo = checkoutCommonUserRole(roleName, userDTO, dept);
		if (StringUtils.isNotEmpty(errInfo)) {
			log.error(errInfo);
			errorMap(errorMap, errInfo, commonUserDTO.getId());
		}

		// 校验用户状态
		String lockflag = StrUtil.cleanBlank(commonUserDTO.getLockFlag());
		if (StringUtils.isEmpty(lockflag)) {
			log.error("用户状态为空");
			errorMap(errorMap, "用户状态为空", commonUserDTO.getId());
		} else {
			if (StringUtils.equals(lockflag, "活跃")) {
				userDTO.setLockFlag("0");
			} else if (StringUtils.equals(lockflag, "休眠")) {
				userDTO.setLockFlag("9");
			} else {
				log.error("用户状态为值不是\"活跃\"或者\"休眠\"");
				errorMap(errorMap, "用户状态为值不是\"活跃\"或者\"休眠\"", commonUserDTO.getId());
			}
		}

		if (ArrayUtils.contains(dept.getSubjectType(), SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode())) {
			userDTO.setCertStatus(TaxHelperCertStatus.UN_CERT.getCode());
		}

		// 记录正确的结果
		userDTO.setCreateTime(LocalDateTime.now());
		userDTO.setDeptId(dept.getDeptId());
		currentList.add(userDTO);

	}

	/**
	 * @Modify: start
	 * @Version: 2021.4.16
	 * @Author: ryz
	 * @Date: 2021/4/21
	 * @Desc: 认证方式 0-人力家 1-税邦云
	 */
	@Override
	@Transactional
	public R batchChannelCert(UserCertificationInput input) {
		SysUser sysUser = baseMapper.selectById(input.getUserId());
		String inputIdCardNumber = input.getIdCardNumber();

		// 校验身份证上的年龄
		if (StringUtils.isNotEmpty(inputIdCardNumber)) {
			// 获取更新操作的用户角色
			List<Integer> roles = sysUserRoleService.list(Wrappers.<SysUserRole>lambdaQuery()
					.eq(SysUserRole::getUserId, input.getUserId()))
					.stream().mapToInt(SysUserRole::getRoleId).boxed().collect(Collectors.toList());
			// 如果角色中包含全职和兼职就需要校验身份证年龄
			if (roles.contains(5) || roles.contains(6)) {
				int ageByIdCard = IdcardUtil.getAgeByIdCard(inputIdCardNumber);
				if (ageByIdCard < 18) {
					return R.failed("年龄未满十八");
				} else if (ageByIdCard > 65) {
					return R.failed("年龄已超过六十五");
				}
			}
		}

		sysUser.setIdCardNumber(inputIdCardNumber);
		SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());

		StringBuilder msg = new StringBuilder();

		for (String subType : input.getSubList()) {
			//人力家
			if (SubjectTypeEnum.TYPE_RENLIJIA.getCode().equals(subType)) {
				Map<String, String> resultMap = certByRenLiJia(sysUser, sysDept);
				msg.append("人力家认证结果:");
				msg.append(resultMap.get("msg"));
				msg.append(";");
			} else if (SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode().equals(subType)) {
				Map<String, String> resultMap = certByShuiBangYun(sysUser, sysDept);
				msg.append("税邦云认证结果:");
				msg.append(resultMap.get("msg"));
				msg.append(";");
			}
		}
		String resultMsg = msg.toString();

		baseMapper.updateById(sysUser);
		return R.ok(null, resultMsg.substring(0, resultMsg.length() - 1));
	}

	private Map<String, String> certByShuiBangYun(SysUser sysUser, SysDept sysDept) {
		Map<String, String> resultMap = new HashMap<>(2);
		resultMap.put("msg", "增员失败");
		SysDeptSub subCondition = new SysDeptSub();
		subCondition.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		subCondition.setDeptId(sysDept.getDeptId());
		subCondition.setSubjectType(SubjectTypeEnum.TYPE_SHUIBANGYUN.getCode());
		SysDeptSub deptSub = sysDeptSubMapper.selectOne(Wrappers.query(subCondition));
		if (null == deptSub || StringUtils.isBlank(deptSub.getAppId())) {
			resultMap.put("msg", "人员所在机构未配置结算信息");
			return resultMap;
		}
		log.info("------开始认证------");
		log.info("------认证渠道：税邦云------");
		log.info("------认证人员姓名：------ {}", sysUser.getRealname());
		log.info("------认证人员手机号：------ {}", sysUser.getUsername());
		log.info("------认证人员身份证：------ {}", sysUser.getIdCardNumber());

		TaxHelperConfig config = new TaxHelperConfig();
		config.setAppId(deptSub.getAppId());
		config.setAppSecrete(deptSub.getAppSecret());
		config.setQueryUrl(deptSub.getQueryUrl());

		TaxHelperAddMemberModel model = new TaxHelperAddMemberModel(config);
		model.setIdCard(sysUser.getIdCardNumber());
		model.setPhone(sysUser.getUsername());
		model.setType(Integer.parseInt(deptSub.getSubjectUserType()));
		model.setName(sysUser.getRealname());
		model.setNotifyUrl("http://localhost:8808");

//		WmDaAgent agent = wmDaAgentMapper.selectByDeptId(sysDept.getDeptId());
//		WmDaDrugEnt drugEnt = wmDaDrugEntMapper.selectByDeptId(sysDept.getDeptId());
//		if (null != agent) {
//			model.setEnterpriseCode(agent.getZjNumber());
//		} else {
//			model.setEnterpriseCode(drugEnt.getEntcode());
//		}
		model.setEnterpriseCode(sysDept.getTaxCode());
		if (StringUtils.isEmpty(model.getEnterpriseCode())) {

			resultMap.put("msg", "未配置企业的统一社会信用代码");
			return resultMap;
		}

		TaxHelperAddMemberRequest request = new TaxHelperAddMemberRequest(model);
		TaxHelperResponse response = taxHelperService.addMembers(request);

		// 记录认证结果
		SysCertResultRecord record = new SysCertResultRecord();
		record.setCode(response.getCode());
		record.setCreateTime(LocalDateTime.now());
		record.setDeptId(sysDept.getDeptId());
		record.setMessage(StringUtils.isNotEmpty(response.getMessage()) ? response.getMessage() : "无");
		record.setStatus(null);
		record.setSubjectType(1);
		record.setMethod("增员");
		record.setUserId(sysUser.getUserId());
		sysCertResultRecordMapper.insert(record);

		if (response.success()) {
			sysUser.setCertStatus(TaxHelperCertStatus.ADD_MEMBER.getCode());
			resultMap.put("msg", "增员成功");
		} else {
			log.info("税邦云增员失败：{},{}，原因是：{}", sysUser.getRealname(), sysUser.getUsername(),
					response.getMessage());
			resultMap.put("msg", "增员失败");
		}
		return resultMap;
	}

	private Map<String, String> certByRenLiJia(SysUser sysUser, SysDept sysDept) {
		Map<String, String> resultMap = new HashMap<>(2);
		resultMap.put("msg", "人力家接口调用失败");
		SysDeptSub subCondition = new SysDeptSub();
		subCondition.setEnableFlag(SubjectTypeEnum.ENABLE_FLAG_TRUE.getCode());
		subCondition.setDeptId(sysDept.getDeptId());
		subCondition.setSubjectType(SubjectTypeEnum.TYPE_RENLIJIA.getCode());
		SysDeptSub deptSub = sysDeptSubMapper.selectOne(Wrappers.query(subCondition));
		if (null == deptSub || StringUtils.isBlank(deptSub.getAppId())) {
			resultMap.put("msg", "人员所在机构未配置结算信息");
			return resultMap;
		}
		log.info("------开始认证------");
		log.info("------认证渠道：人力家------");
		log.info("------认证人员姓名：------ {}", sysUser.getRealname());
		log.info("------认证人员手机号：------ {}", sysUser.getUsername());
		log.info("------认证人员身份证：------ {}", sysUser.getIdCardNumber());

		DingConfig config = new DingConfig();
		config.setAppId(deptSub.getAppId());
		config.setAppSecret(deptSub.getAppSecret());
		config.setQueryUrl(deptSub.getQueryUrl());

		Map map = new HashMap();
		map.put("name", sysUser.getRealname());
		map.put("mobile", sysUser.getUsername());
		map.put("idCard", sysUser.getIdCardNumber());
		map.put("idType", "1");
		List certList = new ArrayList();
		certList.add(map);

		EmployCheckResponse response = dingService.check(config, certList);
		if (!response.isSuccess()) {
			resultMap.put("msg", "人力家接口调用失败");
			return resultMap;
		}
		// 接口请求成功，但是接口返回的状态还需区分checkStatus，1:验证通过，状态改成已提交，2:验证不通过，状态改成认证失败
		List<EmployCheckResultItem> freelancesResult = response.getData().getFreelancesResult();
		if (CollectionUtils.isNotEmpty(freelancesResult)) {
			for (EmployCheckResultItem employCheckResultItem : freelancesResult) {
				if (employCheckResultItem.getIdCard().equals(sysUser.getIdCardNumber())) {
					// 验证通过
					if (employCheckResultItem.getCheckStatus() == 1) {
						sysUser.setRljCertStatus(DingEnum.CER_STATUS_3.getType());
						resultMap.put("msg", "认证提交成功");
						continue;
					} else {// 验证不通过
						if ("1014".equals(employCheckResultItem.getCheckRemark())) {
							log.info("认证返回1014按成功处理：{},{}", sysUser.getRealname(),
									sysUser.getUsername());
							sysUser.setRljCertStatus(DingEnum.CER_STATUS_3.getType());
							resultMap.put("msg", "认证提交成功");
							continue;
						}
						if ("1018".equals(employCheckResultItem.getCheckRemark())) {
							log.info("认证返回1018按处理中处理：{},{}", sysUser.getRealname(),
									sysUser.getUsername());
							sysUser.setRljCertStatus(DingEnum.CER_STATUS_3.getType());
							resultMap.put("msg", "认证提交成功");
							continue;
						}
						if ("1019".equals(employCheckResultItem.getCheckRemark())) {
							log.info("认证返回1019按成功处理：{},{}", sysUser.getRealname(),
									sysUser.getUsername());
							sysUser.setRljCertStatus(DingEnum.CER_STATUS_1.getType());
							resultMap.put("msg", "认证成功");
							continue;
						}
						if ("1020".equals(employCheckResultItem.getCheckRemark())) {
							log.info("认证返回1020按认证失败处理：{},{}", sysUser.getRealname(),
									sysUser.getUsername());
							sysUser.setRljCertStatus(DingEnum.CER_STATUS_2.getType());
							resultMap.put("msg", "认证失败");
							continue;
						}
						sysUser.setRljCertStatus(DingEnum.CER_STATUS_2.getType());
						resultMap.put("msg", "认证失败");
						log.info("认证失败:" + employCheckResultItem.getCheckRemark());
					}
				}
			}
		} else {
			sysUser.setRljCertStatus(DingEnum.CER_STATUS_2.getType());
			resultMap.put("msg", "认证失败");
		}

		return resultMap;
	}

	/**
	 * 保存用户信息
	 *
	 * @param userDto DTO 对象
	 * @return success/fail
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveUser(UserDTO userDto) {


		SysUser sysUser = new SysUser();
		if (null != userDto.getUsername()) {
			sysUser.setPassword(userDto.getUsername().substring(5));
			userDto.setPassword(userDto.getUsername().substring(5));
		}
		BeanUtils.copyProperties(userDto, sysUser);
		sysUser.setDelFlag(CommonConstants.STATUS_NORMAL);
		sysUser.setW1(Md5Utils.getMD5(userDto.getPassword().getBytes()));
		sysUser.setPassword(ENCODER.encode(userDto.getPassword()));
		sysUser.setPlatId(userDto.getPhone());

		//TODO 添加人员增加认证信息  身份证 实名认证状态


		baseMapper.insert(sysUser);

		if (userDto.getRole().contains(5) || userDto.getRole().contains(6)) {
			redisTemplate.opsForValue().set("user_add_notice_key:" + sysUser.getUserId(), sysUser.getUserId());
		}

		List<SysUserRole> userRoleList = userDto.getRole().stream().map(roleId -> {
			SysUserRole userRole = new SysUserRole();
			userRole.setUserId(sysUser.getUserId());
			userRole.setRoleId(roleId);
			return userRole;
		}).collect(Collectors.toList());
		System.out.println("-----" + userRoleList.size());
		System.out.println("-------" + userRoleList.toString());
		return sysUserRoleService.saveBatch(userRoleList);
	}

	/**
	 * 通过查用户的全部信息
	 *
	 * @param sysUser 用户
	 * @return
	 */
	@Override
	public UserInfo findUserInfo(SysUser sysUser) {
		UserInfo userInfo = new UserInfo();
		userInfo.setSysUser(sysUser);
		// 设置角色列表 （ID）
		List<Integer> roleIds = sysRoleService.findRolesByUserId(sysUser.getUserId()).stream().map(SysRole::getRoleId)
				.collect(Collectors.toList());
		userInfo.setRoles(ArrayUtil.toArray(roleIds, Integer.class));

		// 设置权限列表（menu.permission）
		Set<String> permissions = new HashSet<>();
		roleIds.forEach(roleId -> {
			List<String> permissionList = sysMenuService.findMenuByRoleId(roleId).stream()
					.filter(menuVo -> StringUtils.isNotEmpty(menuVo.getPermission())).map(MenuVO::getPermission)
					.collect(Collectors.toList());
			permissions.addAll(permissionList);
		});
		userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
		return userInfo;
	}

	/**
	 * 分页查询用户信息（含有角色信息）
	 *
	 * @param page    分页对象
	 * @param userDTO 参数列表
	 * @return
	 */
	@Override
	public IPage getUsersWithRolePage(Page page, UserDTO userDTO) {
		return baseMapper.getUserVosPage(page, userDTO, new DataScope());
	}

	/**
	 * 分页查询用户信息（含有角色信息）
	 *
	 * @param page    分页对象
	 * @param userDTO 参数列表
	 * @return
	 */
	@Override
	public IPage getUsersWithRolePageNoLock(Page page, UserDTO userDTO) {
		return baseMapper.getUserVosPageNoLock(page, userDTO, new DataScope());
	}

	@Override
	public IPage selectUserList(Page page, UserDTO userDTO) {
		if (SecurityUtils.getRoles().contains(1) || SecurityUtils.getRoles().contains(2)) {
			return baseMapper.getUserVosPage(page, userDTO, new DataScope());
		}
		Integer deptId = userDTO.getDeptId();
//		if (null != userDTO.getDeptId()) {
//			deptId = userDTO.getDeptId();
//		}
		userDTO.setDeptId(SecurityUtils.getUser().getDeptId());
//		if(SecurityUtils.getRoles().contains(7)) {
//			List Listrole = new ArrayList();
//			Listrole.add(7);
//			userDTO.setRole(Listrole);
//		}
		List<UserVO> userList = sysUserMapper.selectByDeptId(userDTO);
		SysDeptRelation sysDeptRelation = new SysDeptRelation();
		sysDeptRelation.setAncestor(userDTO.getDeptId());
		List<SysDeptRelation> sysDeptRelationList = sysDeptRelationMapper.selectListByAncestor(sysDeptRelation);
		List<Integer> ids1 = sysDeptRelationList.stream().map(p -> p.getDescendant()).collect(Collectors.toList());
		List<UserVO> userList1 = new ArrayList<>();
		List<UserVO> userList2 = new ArrayList<>();
		for (Integer id : ids1) {
			userDTO.setDeptId(id);
			List<UserVO> userList3 = sysUserMapper.selectByDeptId(userDTO);
			userList1.addAll(userList3);
		}
		List<Integer> ids2 = userList1.stream().map(p -> p.getUserId()).collect(Collectors.toList());
		for (int i = 0; i < userList1.size(); i++) {
			if (userList1.get(i).getRoleList().size() != 0) {
				if (userList1.get(i).getRoleList().get(0).getRoleId().equals(4)) {
					userDTO.setUserId(ids2.get(i));
					UserVO userVO = sysUserMapper.selectByUserId(userDTO);
					userList2.add(userVO);
				}
			}
		}
		userList.addAll(userList2);
		List<Integer> ids = userList.stream().map(p -> p.getUserId()).collect(Collectors.toList());
		for (int i = 0; i < userList.size(); i++) {
			List<SysRole> sysRoleList1 = sysRoleService.findRolesByUserId(ids.get(i));
			userList.get(i).setRoleList(sysRoleList1);
		}

		if (null != deptId) {
			userList = userList.stream().filter(item -> deptId.equals(item.getDeptId())).collect(Collectors.toList());
			;
		}


		//每页数据条数
		Page<UserVO> page1 = new Page<>();
		int current = new Long(page.getCurrent()).intValue();
		int size = new Long(page.getSize()).intValue();

		int count = userList.size();
		List<UserVO> pageList = new ArrayList<>();
		//计算当前页第一条数据的下标
		int currId = current > 1 ? (current - 1) * size : 0;
		for (int i = 0; i < size && i < count - currId; i++) {
			pageList.add(userList.get(currId + i));
		}
		page1.setSize(size);
		page1.setCurrent(current);
		page1.setTotal(count);
		//计算分页总页数
		page1.setPages(count % 10 == 0 ? count / 10 : count / 10 + 1);
		page1.setRecords(pageList);
		return page1;
	}

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

	/**
	 * 删除用户
	 *
	 * @param sysUser 用户
	 * @return Boolean
	 */
	@Override
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#sysUser.username")
	public Boolean deleteUserById(SysUser sysUser) {
		sysUserRoleService.deleteByUserId(sysUser.getUserId());
		this.removeById(sysUser.getUserId());
		return Boolean.TRUE;
	}

	@Override
	@Caching(evict = {@CacheEvict(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#userDto.username"),
			@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")})
	public R<Boolean> updateUserInfo(UserDTO userDto) {
		UserVO userVO = baseMapper.getUserVoById(userDto.getUserId());
		SysUser sysUser = new SysUser();
		String newPwd = ENCODER.encode(userDto.getNewpassword1());
		if (StrUtil.isNotBlank(userDto.getPassword()) && StrUtil.isNotBlank(userDto.getNewpassword1())) {
			if (ENCODER.matches(userDto.getPassword(), userVO.getPassword())) {
				sysUser.setPassword(newPwd);
			} else {
				log.info("原密码错误，修改密码失败:{}", userDto.getUsername());
				return R.failed("原密码错误，修改失败");
			}
		}
		sysUser.setPhone(userDto.getPhone());
		sysUser.setUserId(userVO.getUserId());
		sysUser.setAvatar(userDto.getAvatar());
		if (null != userDto.getNewpassword1()) {
			sysUser.setW1(Md5Utils.getMD5(userDto.getNewpassword1().getBytes()));
		}


		List<SysUser> list = this.getUserByPlatId(userVO.getPlatId());

		if (this.updateById(sysUser)) {
			for (SysUser sysUser1 : list) {
				if (!sysUser.getUserId().equals(sysUser1.getUserId())) {
					sysUser1.setPassword(newPwd);
					this.updateById(sysUser1);
				}
			}
		}

		return R.ok();
	}

//	@Override
//	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
//	public R<Boolean> updateUserInfo(UserDTO userDto) {
////		UserVO userVO = baseMapper.getUserVoByUsername(userDto.getUsername());
//		/**
//		 * 20210102
//		 */
//		UserVO userVO = baseMapper.getUserVoById(userDto.getUserId());
//		SysUser sysUser = new SysUser();
//		if (StrUtil.isNotBlank(userDto.getPassword()) && StrUtil.isNotBlank(userDto.getNewpassword1())) {
//			if (ENCODER.matches(userDto.getPassword(), userVO.getPassword())) {
//				sysUser.setPassword(ENCODER.encode(userDto.getNewpassword1()));
//			} else {
//				log.info("原密码错误，修改密码失败:{}", userDto.getUsername());
//				return R.failed("原密码错误，修改失败");
//			}
//		}
//		sysUser.setPhone(userDto.getPhone());
//		sysUser.setUserId(userVO.getUserId());
//		sysUser.setAvatar(userDto.getAvatar());
//		if (null != userDto.getNewpassword1()) {
//			sysUser.setW1(Md5Utils.getMD5(userDto.getNewpassword1().getBytes()));
//		}
//
//
//		if (null != userDto.getDeptId()) {
//			SysDept sysDept = sysDeptService.getById(userDto.getDeptId());
//			if (null != sysDept) {
//				sysUser.setDrugEntId(sysDept.getLevel1Id() + "");
//			}
//		}
//		return R.ok(this.updateById(sysUser));
//	}


	@Override
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
	public R<Boolean> updateUserInfoVo(UserVO userVO) {
		SysUser sysUser = super.getById(userVO.getUserId());
		if (null != sysUser) {
			sysUser.setWxOpenid(userVO.getWxOpenid());
			sysUser.setUserId(userVO.getUserId());
			sysUser.setAvatar(userVO.getAvatar());
			return R.ok(this.updateById(sysUser));
		}

		return R.ok();
	}

	@Override
	@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
	public Boolean updateUser(UserDTO userDto) {
		SysUser sysUser = new SysUser();
		BeanUtils.copyProperties(userDto, sysUser);
		sysUser.setUpdateTime(LocalDateTime.now());
		if (null != userDto.getPassword()) {
			sysUser.setW1(Md5Utils.getMD5(userDto.getPassword().getBytes()));
		}
		if (StrUtil.isNotBlank(userDto.getPassword())) {
			sysUser.setPassword(ENCODER.encode(userDto.getPassword()));
		}

		this.updateById(sysUser);

		sysUserRoleService
				.remove(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;
	}

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

		SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
		if (sysDept == null) {
			return null;
		}

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

	/**
	 * 获取当前用户的子部门信息
	 *
	 * @return 子部门列表
	 */
	private List<Integer> getChildDepts() {
		Integer deptId = SecurityUtils.getUser().getDeptId();
		// 获取当前部门的子部门
		return sysDeptRelationService
				.list(Wrappers.<SysDeptRelation>query().lambda().eq(SysDeptRelation::getAncestor, deptId)).stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
	}


	public List<SysUser> getUserByPlatId(String platId) {
		SysUser sysUser = new SysUser();
		sysUser.setDelFlag("0");
		sysUser.setPlatId(platId);
		return super.list(Wrappers.<SysUser>query(sysUser));
	}

	@Override
	public List<UserVO> getUserVoByPlatId(UserDTO userDTO) {
		List<Integer> list = new ArrayList<>();
		list.add(5);
		list.add(6);
		list.add(10);
		// 患者教育-HCP角色
		list.add(13);
		userDTO.setRole(list);
		return baseMapper.getUserVoByPlatId(userDTO);
	}

	@Override
	public R updatePwd(UserPwd userPwd) {
		String p1 = userPwd.getP1();
		String p2 = userPwd.getP2();
		String userName = userPwd.getUserName();
		String code = userPwd.getCode();

//		String key = CacheConstants.DEFAULT_CODE_KEY + LoginTypeEnum.SMS.getType() + StringPool.AT + userName;
//
//		redisTemplate.setKeySerializer(new StringRedisSerializer());
//
//		if (!redisTemplate.hasKey(key)) {
//			throw new ValidateCodeException("请输入正确验证码");
//		}
//
//		Object codeObj = redisTemplate.opsForValue().get(key);
//
//		if (codeObj == null) {
//			throw new ValidateCodeException("请输入正确验证码");
//		}
//
//		String saveCode = codeObj.toString();
//		if (StrUtil.isBlank(saveCode)) {
//			redisTemplate.delete(key);
//			throw new ValidateCodeException("请输入正确验证码");
//		}
//
//		if (!StrUtil.equals(saveCode, code)) {
//			redisTemplate.delete(key);
//			throw new ValidateCodeException("请输入正确验证码");
//		}
//
		List<SysUser> userList = baseMapper.selectList(Wrappers.<SysUser>lambdaQuery().
				eq(SysUser::getUsername, userName));
		if (CollectionUtils.isEmpty(userList)) {
			return R.failed("用户不存在");
		}

		if (!p1.equals(p2)) {
			return R.failed("两次密码输入不一致");
		}
		for (SysUser sysUser : userList) {
			sysUser.setUserId(sysUser.getUserId());
			sysUser.setW1(Md5Utils.getMD5(p1.getBytes()));
			sysUser.setPassword(ENCODER.encode(p1));
			baseMapper.updateById(sysUser);
		}

//		redisTemplate.delete(key);
		return R.ok();
	}

	@Override
	public SysUser getByIdIgnore(String id) {
		return baseMapper.getByIdIgnore(id);
	}
}
