package com.storlead.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.storlead.framework.auth.vo.LoginUser;
import com.storlead.framework.common.result.Result;
import com.storlead.framework.common.util.RsaUtils;
import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
import com.storlead.framework.common.ecode.PasswordEncoder;
import com.storlead.framework.common.thread.ThreadPoolUtil;
import com.storlead.framework.util.LoginUserUtil;
import com.storlead.user.mapper.UserMapper;
import com.storlead.user.model.UserInfo;
import com.storlead.user.model.UserQueryModel;
import com.storlead.user.pojo.entity.*;
import com.storlead.user.pojo.vo.UserVo;
import com.storlead.user.pojo.vo.WxUserVO;
import com.storlead.user.service.*;
import com.storlead.user.util.PinyinUtil;
import com.storlead.thirdparty.api.enums.ThirdPartyChannel;
import com.storlead.thirdparty.api.dto.ThirdPartyUserSyncDTO;
import com.storlead.thirdparty.api.service.ThirdPartyUserSyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.hutool.core.date.DateTime.now;


/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @Author: scott
 * @Date: 2018-12-20
 */

@Slf4j
@Service
public class UserServiceImpl extends MyBaseServiceImpl<UserMapper, UserEntity> implements IUserService {

	@Resource
	private UserMapper userMapper;
	@Resource
	private ICompanyService companyService;
	@Resource
	private ISubCompanyService subCompanyService;
	@Resource
	private IDepartService departService;
	@Resource
	private IJobService jobService;
	@Resource
	private ThirdPartyUserSyncService thirdPartyUserSyncService;
	@Resource
	private PasswordEncoder passwordEncoder;
	@Resource
	private IHrmcompanyService hrmcompanyService;
	@Resource
	private IHrmsubcompanyService hrmsubcompanyService;
	@Resource
	private IHrmdepartmentService hrmdepartmentService;
	@Resource
	private IHrmjobtitlesService hrmjobtitlesService;
	@Resource
	private IHrmresourceService hrmresourceService;
	@Override
	public UserEntity getUserByName(String username) {
        UserEntity user = this.baseMapper.getUserByName(username);
        if(ObjectUtils.isEmpty(user)){
        	return user;
		}
		return user;
	}

	@Override
	public UserEntity getUserByMobile(String mobile) {
		UserEntity user = this.baseMapper.getUserByMobile(mobile);
		if(ObjectUtils.isEmpty(user)){
			return user;
		}
		return user;
	}

	@Override
	public List<UserInfo> getUserListBySearch(UserQueryModel userQueryModel) {
		return this.baseMapper.queryList(userQueryModel);
	}

	@Override
	public List<UserEntity> getUserListByStaffIds(Collection<Long> staffIds) {
		if(CollectionUtils.isEmpty(staffIds)){
			return new ArrayList<>();
		}
		LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper();
		// queryWrapper.select(UserEntity::getId, UserEntity::getRealName, UserEntity::getAvatar);
		if(staffIds!=null&&!staffIds.isEmpty()) {
			queryWrapper.in(UserEntity::getId, staffIds);
		}
		return this.baseMapper.selectList(queryWrapper);
	}

	@Override
	public List<Long> getAllSubordinate(Long currentUserId) {
		return this.baseMapper.getAllSubordinate(currentUserId);
	}


	/**
	 * 同步OA组织架构
	 * 包含公司/分公司/部门/岗位/用户
	 * 最后再同步企业微信的头像信息
	 *
	 * @return com.storlead.web.model.entity.User
	 * @author blank
	 * @date 2021-3-8 下午 3:22
	 */
	@Override
	public Boolean syncOa() {
		try {
			ThreadPoolUtil.execute(new Runnable() {
				@Override
				public void run() {
					Long d = System.currentTimeMillis();
					log.error("syncCompany--------------begin = "+d);
					boolean c = syncCompany();
					boolean sc = syncDept();
					boolean sj = syncJob();
					if (c && sc && sj) {
						syncUser();
					}
					log.error("syncCompany--------------end = "+(System.currentTimeMillis() - d));
				}
			});
		}catch (Exception e) {
			log.error("-------------------> syncOa error = ",e);
			return false;
		}
		log.error("-------------------> syncOa ok");
		return true;
	}

	/**
	 * 同步project公司
	 *
	 * @return java.lang.Boolean
	 * @author YPZ
	 * @date 2022-2-23 下午 4:34
	 */
	@Override
	public Boolean syncCompany() {
		Integer companyCode = 99;
		Integer subCode = 99;
		LoginUser user = LoginUserUtil.getLoginUser();
		if (user == null) {
			user = new LoginUser().setId(1L);
		}
		//读取OA总公司数据
		List<Hrmcompany> hrmcompanyList = hrmcompanyService.list();

		Map companyMap = new HashMap();
		List<CompanyEntity> companyList = new ArrayList<>();
		for (Hrmcompany hrmcompany : hrmcompanyList) {
			++ companyCode;
			CompanyEntity company = new CompanyEntity().setRouteCode(companyCode.toString())
					.setId(hrmcompany.getId().longValue())
					.setName(hrmcompany.getCompanyname())
					.setDesc(hrmcompany.getCompanydesc());
			companyList.add(company);
			companyMap.put(company.getId(),companyCode.toString());

		}
		for (CompanyEntity mcompany : companyList) {
			CompanyEntity oldConpany = companyService.getById(mcompany.getId());
			if (Objects.nonNull(oldConpany)) {
				mcompany.setManagerId(oldConpany.getManagerId());
			}
		}
		//保存总公司
		companyService.remove(new LambdaQueryWrapper<CompanyEntity>().eq(CompanyEntity::getDataSource,0));
		boolean saveCompany = companyService.saveBatch(companyList);
		log.info("保存总公司: {}", saveCompany);
		//读取OA分公司数据
		List<Hrmsubcompany> hrmsubcompanyList = hrmsubcompanyService.list();
		List<SubCompanyEntity> subCompanys = subCompanyService.list();
		Map<Long, SubCompanyEntity> subConpanyMap = new HashMap<>();
		if (!CollectionUtils.isEmpty(subCompanys)) {
			subConpanyMap = subCompanys.stream().collect(Collectors.toMap(SubCompanyEntity::getId, a -> a, (u1, u2) -> u1));
		}
		List<SubCompanyEntity> subCompanyList = new ArrayList<>();
		for (Hrmsubcompany hrmsubcompany : hrmsubcompanyList) {
			++ subCode;
			String topCode = companyMap.get(hrmsubcompany.getCompanyid()).toString();
			SubCompanyEntity subCompany = (SubCompanyEntity) new SubCompanyEntity().setRouteCode(topCode+","+subCode.toString()).setId(hrmsubcompany.getId())
					.setCompanyId(hrmsubcompany.getCompanyid()).setName(hrmsubcompany.getSubcompanyname()).setDesc(hrmsubcompany.getSubcompanydesc())
					.setSort(hrmsubcompany.getShoworderoftree());
			SubCompanyEntity oldSubConpany = subConpanyMap.get(hrmsubcompany.getId());
			if (Objects.nonNull(oldSubConpany)) {
				subCompany.setLeaderId(oldSubConpany.getLeaderId());
				subCompany.setLeaderName(oldSubConpany.getLeaderName());
				subCompany.setIsDelete(oldSubConpany.getIsDelete());
				subCompany.setEnabled(oldSubConpany.getEnabled());
			}
			subCompanyList.add(subCompany);
		}
		//保存分公司
	   subCompanyService.remove(new LambdaQueryWrapper<SubCompanyEntity>().eq(SubCompanyEntity::getDataSource,0));
		boolean saveSubCompany = subCompanyService.saveBatch(subCompanyList);
		log.info("保存分公司: {}", saveSubCompany);
		return saveCompany && saveSubCompany;

	}

	/**
	 * 同步OA部门
	 *
	 * @return java.lang.Boolean
	 * @author blank
	 * @date 2021-3-23 下午 4:36
	 */
	@Override
	public Boolean syncDept() {

		List<SubCompanyEntity> companies = subCompanyService.list();
		List<DeptEntity> deptes = departService.list();
		Map<Long, DeptEntity> deptMap = new HashMap<>();
		if (!CollectionUtils.isEmpty(deptes)) {
			deptMap = deptes.stream().collect(Collectors.toMap(DeptEntity::getId, a -> a, (u1, u2) -> u1));
		}

		Map companyMap = new HashMap();
		companies.forEach(c -> {
			companyMap.put(c.getId(),c.getRouteCode());
		});
		LoginUser currentUser = LoginUserUtil.getLoginUser();
		if (currentUser == null) {
			currentUser = new LoginUser().setId(0L);
		}
		List<Hrmdepartment> hrmdepartmentList = hrmdepartmentService.list();
		List<DeptEntity> deptList = new ArrayList<>();
		for (Hrmdepartment hrmdepartment : hrmdepartmentList) {

			DeptEntity oldDept = deptMap.get(hrmdepartment.getId());
			DeptEntity dept = new DeptEntity();
			dept.setId(hrmdepartment.getId());
			if (Objects.nonNull(oldDept)) {
				dept.setManagerId(oldDept.getManagerId());
				dept.setSubManagerIds(oldDept.getSubManagerIds());
				dept.setLeaderName(oldDept.getLeaderName());
				dept.setEnabled(oldDept.getEnabled());
			}
			dept.setName(hrmdepartment.getDepartmentname());
			dept.setSubCompanyId(hrmdepartment.getSubcompanyid1());
			dept.setPid(hrmdepartment.getSupdepid());
			dept.setSort(hrmdepartment.getShoworderoftree());
			dept.setCreateBy(currentUser.getId());
			dept.setCreateTime(new Date());
			deptList.add(dept);
		}
		List<DeptEntity> topDept = deptList.stream().filter(d -> Long.valueOf(0).equals(d.getPid())).collect(Collectors.toList());
		Integer deptCode = 99;
		List<DeptEntity> resds = new ArrayList<>();
		for (DeptEntity dept : topDept) {
			 ++deptCode;
			 dept.setRouteCode(companyMap.get(dept.getSubCompanyId()).toString()+","+deptCode.toString());
			 List<DeptEntity> ds = assembDept(deptList,dept);
			 if(!CollectionUtils.isEmpty(ds)) {
				 resds.addAll(ds);
			 }
			resds.add(dept);
		}

		departService.remove(new LambdaQueryWrapper<DeptEntity>().eq(DeptEntity::getDataSource,0));
		boolean saveDept = departService.saveOrUpdateBatch(resds);
		return  saveDept;
	}

	public List<DeptEntity> assembDept(List<DeptEntity> depts,DeptEntity dept) {
		List<DeptEntity> ds = new ArrayList<>();
		String pCode = dept.getRouteCode();
		Integer deptCode = 99;
		for (DeptEntity tree : depts) {
			if (tree.getPid().equals(dept.getId())) {
				++deptCode;
				tree.setRouteCode(pCode+","+deptCode.toString());
				ds.add(tree);
				List<DeptEntity> ds1 = assembDept(depts,tree);
				if (!CollectionUtils.isEmpty(ds1)) {
					ds.addAll(ds1);
				}
			}
		}
		return ds;
	}

	/**
	 * 同步OA岗位
	 *
	 * @return java.lang.Boolean
	 * @author blank
	 * @date 2021-3-23 下午 4:36
	 */
	@Override
	public Boolean syncJob() {

		LoginUser currentUser = LoginUserUtil.getLoginUser();
		if (currentUser == null) {
			currentUser = new LoginUser().setId(0L);
		}
		List<Hrmjobtitles> list = hrmjobtitlesService.list();
		List<JobEntity> jobList = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			Hrmjobtitles hrmjobtitles = list.get(i);
			JobEntity job = new JobEntity();
			job.setId(hrmjobtitles.getId());
			job.setName(hrmjobtitles.getJobtitlename());
			job.setDesc(hrmjobtitles.getJobresponsibility());
			job.setSort(i);
			job.setEnabled(true);
			job.setCreateBy(currentUser.getId());
			job.setCreateTime(new Date());
			jobList.add(job);
		}

		//先删除所有岗位
		jobService.remove(new LambdaQueryWrapper<JobEntity>().eq(JobEntity::getDataSource,0));
		boolean saveJob = jobService.saveBatch(jobList);
		log.info("保存岗位: {}", saveJob);
		return saveJob;
	}

	/**
	 * 同步OA用户
	 *
	 * @return java.lang.Boolean
	 * @author blank
	 * @date 2021-3-23 下午 4:34
	 */
	@Override
	public Boolean syncUser() {
		Long d = System.currentTimeMillis();
		log.error("syncUser--------------begin = "+d);
		//先同步 OA流程的员工转正离职日期 到 OA人力资源表
		hrmresourceService.updatePermanentDate();
		log.error("syncUser--------------end1 = "+(System.currentTimeMillis()-d));
		hrmresourceService.updateResignDate();
		log.error("syncUser--------------end2 = "+(System.currentTimeMillis()-d));

		LoginUser currentUser = LoginUserUtil.getLoginUser();
		if (currentUser == null) {
			currentUser = new LoginUser().setId(0L);
		}
		List<UserEntity> userList = hrmresourceService.getUserList();
		log.error("syncUser--------------end3 = "+(System.currentTimeMillis()-d));
		List<UserEntity> dbUserList = list();
		List<UserEntity> addList = new ArrayList<>();
		List<UserEntity> updateList = new ArrayList<>();

		List<DeptEntity> depts = departService.list();
		log.error("syncUser--------------end4 = "+(System.currentTimeMillis()-d));
		Map deptMap = new HashMap();
		depts.forEach(c -> {
			deptMap.put(c.getId(),c.getRouteCode());
		});
		// 默认密码
		String defaultPassWord = "storlead123456";
		log.error("syncUser--------------end5 = "+(System.currentTimeMillis()-d));
		for (UserEntity user : userList) {
			UserEntity userDb = dbUserList.stream().filter(u -> u.getId().equals(user.getId())).findFirst().orElse(null);
			String routeCode =  Objects.isNull(deptMap.get(user.getDeptId())) ? "" : deptMap.get(user.getDeptId()).toString();
			if (userDb == null) {
				//新增的用户
				user
						.setUserName(user.getMobile()).setOrgRouteCode(routeCode)
						.setPassword(passwordEncoder.encode(defaultPassWord))
						.setDataSource(0)
						.setCreateBy(currentUser.getId())
						.setEnabled(true)
						.setOwnerBy(user.getId());
				addList.add(user);
			} else {
				//禁用离职状态的用户
				if (user.getStatus()!=null && Integer.parseInt(user.getStatus()) == 5) {
					user.setEnabled(false);
				}

				user
						.setOrgRouteCode(routeCode)
						.setUserName(user.getMobile())
						.setOwnerBy(user.getId());
				updateList.add(user);
			}
		}
		log.error("syncUser--------------end6 = "+(System.currentTimeMillis()-d));
		if (!CollectionUtils.isEmpty(addList)) {
			this.saveBatch(addList);
		}
		if (CollectionUtils.isEmpty(updateList)) {
			syncUserOpenIdFormTencent();
		}
		log.error("syncUser--------------end7 = "+(System.currentTimeMillis()-d));
		if (!CollectionUtils.isEmpty(updateList)) {
			ThreadPoolUtil.execute(new Runnable() {
				@Override
				public void run() {
					saveOrUpdateBatch(updateList);
					syncUserOpenIdFormTencent();

				}
			});
		}
		log.error("syncUser--------------end8 = "+(System.currentTimeMillis()-d));


		return true;
	}

	/**
	 * 从企业微信同步 xwork_userid 头像
	 *
	 * @author blank
	 * @date 2021-6-15 上午 11:58
	 */
	public boolean syncUserOpenIdFormTencent() {
		List<UserEntity> list = this.list();

		List<ThirdPartyUserSyncDTO> us = new ArrayList<>();
		List<ThirdPartyUserSyncDTO> finalUs = us;
		list.forEach(a -> {
			ThirdPartyUserSyncDTO v = new ThirdPartyUserSyncDTO();
			BeanUtils.copyProperties(a,v);
			finalUs.add(v);
		});
		List<ThirdPartyUserSyncDTO> syncedUsers = thirdPartyUserSyncService.syncUserOpenId(ThirdPartyChannel.WECOM, finalUs);
		if (CollectionUtils.isEmpty(syncedUsers)) {
			return false;
		}

		list = new ArrayList<>();
		List<UserEntity> finalList = list;
		syncedUsers.forEach(a -> {
			UserEntity v = new UserEntity();
			BeanUtils.copyProperties(a,v);
			finalList.add(v);
		});
		boolean b = saveOrUpdateBatch(list);
		return b;
	}

	/**
	 * 修改用户头像
	 *
	 * @return boolean
	 * @author YPZ
	 * @date 2022-3-2
	 */
	@Override
	public boolean updateAvater() {
		return syncUserOpenIdFormTencent();
	}

	@Override
	public Result<?> updateUserPass(UserForm param) {
		LoginUser loginUser = LoginUserUtil.getLoginUser();
		UserEntity sysUser = this.baseMapper.getUserByName(loginUser.getUserName());
		if (loginUser == null) {
			return Result.error("未登陆");
		}
		try {
			param.setPassword(RsaUtils.decryptByPrivateKey(RsaUtils.PRIVATE_KEY, param.getPassword()));
			param.setNewPass(RsaUtils.decryptByPrivateKey(RsaUtils.PRIVATE_KEY, param.getNewPass()));
		}catch (Exception e){
			log.info("密码简析错误",e);
			return Result.error("修改失败");
		}
		if (!passwordEncoder.matches(param.getPassword(), sysUser.getPassword())) {
			return Result.error("旧密码错误");
		}
		// SystemConfigItemCacheUtil.checkPasswordStrength(param.getPassword());
		if (param.getPassword().equals(param.getNewPass())) {
			return Result.error("新旧密码不能相同");
		}

		boolean b = this.updateById(new UserEntity(loginUser.getId(), loginUser.getUserName(), passwordEncoder.encode(param.getNewPass())));
		if(b){
			// 生成token
			return  Result.result("修改成功");
		}
		return Result.error("修改密码失败");
	}

	/**
	 * 根据用户名获取用户
	 *
	 * @param userName 用户名
	 * @return com.storlead.model.entity.User
	 * @author blank
	 * @date 2021-1-28 上午 10:59
	 */
	@Override
	public UserEntity getUserByUserName(String userName) {
		return this.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserName, userName), false);
	}

	/**
	 * 根据用户角色查询可查看用户列表
	 *
	 * @return com.storlead.model.entity.User
	 * @author YPZ
	 * @date 2022-4-24
	 */
	@Override
	public List<Long> getListByUserRole() {
		LoginUser loginUser = LoginUserUtil.getLoginUser();
		return userMapper.getListByUserRole(loginUser);
	}

	@Override
	public List<UserVo> searchHomeUserList(IPage<UserVo> page, Wrapper wrapper) {
		return userMapper.searchHomeUserList(page,wrapper);
	}

	/**
	 * 查询指定用户的直接下级
	 * @param userId
	 * @return
	 */
	@Override
	public List<UserEntity> getDirectSubUserList(Long userId) {
		return userMapper.selectList(new LambdaUpdateWrapper<UserEntity>().eq(UserEntity::getManagerId,userId).eq(UserEntity::getEnabled,1).eq(UserEntity::getIsDelete,0));
	}

	@Override
	public UserVo getUserInfoById(Long userId) {
		return userMapper.getUserInfoById(userId);
	}

	@Override
	public List<WxUserVO> getPingyinUserList(UserQueryModel userQueryModel) {
		List<UserInfo> list = getUserListBySearch(userQueryModel);
		List<WxUserVO> wxUserInfoList = PinyinUtil.wxUserList(list);
		return wxUserInfoList;
	}

	@Override
	public void updateLastAcTime(Long userId) {
		LambdaUpdateWrapper<UserEntity> update = new LambdaUpdateWrapper();
		update.eq(UserEntity::getId,userId);
		update.set(UserEntity::getLastActivityTime,now());
		update(update);
	}

	@Override
	public Set<Long> getUserRoleIdsByApiUrl(Long userId,String apiUrl){
		return  baseMapper.selectUserRoleIdsByApiUrl(userId,apiUrl);
	}

	@Override
	public Set<Long> selectUserRoleIdsByMenuId(Long userId,String menuId){
		return  baseMapper.selectUserRoleIdsByMenuId(userId,menuId);
	}

	@Override
	public Set<Long> selectUserRoleIdsByCommonScopeType(Long userId, String commonScopeType) {
		return  baseMapper.selectUserRoleIdsByCommonScopeType(userId,commonScopeType);
	}

	@Override
	public Set<Long> getUserIdsByDeptIds(List<Long> deptIds) {
		return baseMapper.getUserIdsByDeptIds(deptIds);
	}

	@Override
	public List<UserEntity> getUserListByIds(List<Long> userIds) {
		LambdaQueryWrapper<UserEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.in(UserEntity::getId, userIds);
		return list(wrapper);
	}

	@Override
	public void updateLastFollowUpTime(List<Long> userIds) {
		baseMapper.updateLastFollowUpTime(userIds);
	}


	@Override
	public Map<Long, UserEntity> IdListToUserMap(List<Long> userList) {
		if(userList!=null && userList.size()>0){
			List<UserEntity> userEntityList = baseMapper.selectBatchIds(userList);
			Map<Long, UserEntity> userMap = userEntityList.stream().collect(Collectors.toMap(UserEntity::getId, Function.identity()));
			return userMap;
		}

		return null;
	}

	@Override
	public List<UserEntity> activeUsers() {
		LambdaQueryWrapper<UserEntity> wrapper =new LambdaQueryWrapper<>();
		wrapper.eq(UserEntity::getEnabled,1);
		return this.list(wrapper);
	}
}
