/*
 *    Copyright (c) 2018-2025, lengleng 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 yifu4cloud.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: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.yifu.archives.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSONObject;
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.yifu.cloud.plus.v1.yifu.archives.entity.TCustomerInfo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeInfo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeeProject;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TSettleDomain;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TCustomerInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TEmployeeInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TEmployeeProjectMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.TEmployeeLogService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TEmployeeProjectService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TSettleDomainService;
import com.yifu.cloud.plus.v1.yifu.archives.vo.EmployeeProjectExportVO;
import com.yifu.cloud.plus.v1.yifu.archives.vo.EmployeeProjectVO;
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.exception.ErrorCodes;
import com.yifu.cloud.plus.v1.yifu.common.core.util.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprCheckProperties;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目档案表
 *
 * @author huyc
 * @date 2022-06-20 09:19:40
 */
@Service
@RequiredArgsConstructor
@EnableConfigurationProperties(DaprCheckProperties.class)
@Log4j2
public class TEmployeeProjectServiceImpl extends ServiceImpl<TEmployeeProjectMapper, TEmployeeProject> implements TEmployeeProjectService {

	private final TEmployeeLogService tEmployeeLogService;

	private final TEmployeeInfoMapper tEmployeeInfoMapper;

	private final TSettleDomainService tSettleDomainService;

	private final TCustomerInfoMapper tCustomerInfoMapper;

	private final DaprCheckProperties daprCheckProperties;

	// 缓存信息
	private final CacheManager cacheManager;

	@Override
	public R addCheck(TEmployeeProject tEmployeeProject) {

		Map<String,Object> map = new HashMap<>();

		//身份证系统中是否已有
		TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectOne(Wrappers.<TEmployeeInfo>query().lambda()
				.eq(TEmployeeInfo::getEmpIdcard, tEmployeeProject.getEmpIdcard())
				.eq(TEmployeeInfo::getDeleteFlag, CommonConstants.STATUS_NORMAL));

		//项目下已有身份证信息
		TEmployeeProject employeeProject = this.getOne(Wrappers.<TEmployeeProject>query().lambda()
				.eq(TEmployeeProject::getEmpIdcard,tEmployeeProject.getEmpIdcard())
				.eq(TEmployeeProject::getDeptNo,tEmployeeProject.getDeptNo())
				.eq(TEmployeeProject::getDeleteFlag,CommonConstants.STATUS_NORMAL));
		if (!Common.isEmpty(employeeProject)) {

			//身份证实名认证
			if (!Common.isEmpty(tEmployeeInfo)) {
				if (!tEmployeeProject.getEmpName().equals(tEmployeeInfo.getEmpName())) {
					return R.failed("姓名和身份证不一致，请确认后再次新增");
				}
			}
			//项目状态为已减项
			if (CommonConstants.dingleDigitIntArray[1] == employeeProject.getProjectStatus()) {
				if (!Common.isEmpty(tEmployeeInfo)) {
					map.put("empProId",tEmployeeProject.getId());
					if (CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()) {
						return new R<>(CommonConstants.dingleDigitIntArray[4],"该人员已减项，是否“复项”",map);
					} else {
						map.put("employeeId", tEmployeeInfo.getId());
						return new R<>(CommonConstants.dingleDigitIntArray[2],"该人员已减档减项，是否“复档复项”",map);
					}
				}
			}
			//状态为草稿、已审核
			if (CommonConstants.dingleDigitIntArray[0] == employeeProject.getStatus() ||
					CommonConstants.dingleDigitIntArray[1] == employeeProject.getStatus()) {
				return R.failed("人员已有该项目信息，禁止重复添加！");
			}
		} else {
			if (Common.isEmpty(tEmployeeInfo)) {
				return R.failed("该人员暂无档案信息，禁止关联项目，如要添加，请先至“在档人员”处建档");
			}
			//判断是否已经减档
			if (tEmployeeInfo.getFileStatus() == CommonConstants.dingleDigitIntArray[1]) {
				map.put("employeeId", tEmployeeInfo.getId());
				return new R<>(CommonConstants.dingleDigitIntArray[3],"该人员在离职库已存在，是否“恢复档案”",map);
			}
		}
		return R.ok();
	}

	@Override
	public R saveEmp(TEmployeeProject tEmployeeProject) {
		//查询人员档案
		TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectOne(Wrappers.<TEmployeeInfo>query().lambda()
				.eq(TEmployeeInfo::getEmpIdcard, tEmployeeProject.getEmpIdcard())
				.eq(TEmployeeInfo::getDeleteFlag, CommonConstants.STATUS_NORMAL));
		if (Common.isNotNull(tEmployeeInfo)) {
			String empNO = getEmpNo(tEmployeeProject.getDeptNo());
			tEmployeeProject.setEmpNo(empNO);
			tEmployeeProject.setEmpId(tEmployeeInfo.getId());
			tEmployeeProject.setProjectSource(CommonConstants.dingleDigitStrArray[5]);
			this.save(tEmployeeProject);
			tEmployeeInfo.setProjectNum(tEmployeeInfo.getProjectNum().intValue() + CommonConstants.ONE_INT);
			tEmployeeInfoMapper.updateById(tEmployeeInfo);
			return R.ok();
		}
		return R.failed("未在人员档案中查到身份信息");
	}

	@Override
	public R reEmpInfo(JSONObject jsonObject) {
		if (Common.isNotNull(jsonObject)) {
			String empId = jsonObject.getString("empId");
			String empProId = jsonObject.getString("empProId");
			TEmployeeInfo tEmployeeInfoOld = tEmployeeInfoMapper.selectById(empId);
			TEmployeeProject tEmployeeProjectOld = this.getById(empProId);
			if (!Common.isEmpty(empId) && Common.isEmpty(empProId)) {
				//复档
				TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectById(empId);
				tEmployeeInfo.setFileStatus(CommonConstants.dingleDigitIntArray[0]);
				tEmployeeInfoMapper.updateById(tEmployeeInfo);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[0],empId,"",tEmployeeInfoOld,tEmployeeInfo);
			} else if (Common.isEmpty(empId) && !Common.isEmpty(empProId)) {
				//复项
				TEmployeeProject tEmployeeProject = this.getById(empProId);
				tEmployeeProject.setProjectStatus(CommonConstants.dingleDigitIntArray[0]);
				this.updateById(tEmployeeProject);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[1],"",empProId,tEmployeeProjectOld,tEmployeeProject);
			} else {
				//复档复项
				TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectById(empId);
				TEmployeeProject tEmployeeProject = this.getById(empProId);
				tEmployeeInfo.setFileStatus(CommonConstants.dingleDigitIntArray[0]);
				tEmployeeInfoMapper.updateById(tEmployeeInfo);
				tEmployeeProject.setProjectStatus(CommonConstants.dingleDigitIntArray[0]);
				this.updateById(tEmployeeProject);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[1],"",empProId,tEmployeeProjectOld,tEmployeeProject);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[0],empId,"",tEmployeeInfoOld,tEmployeeInfo);
			}
		} else {
			return R.failed("传参为空！");
		}
		return R.ok();
	}

	@Override
	public R deleteEmpPro(TEmployeeProject tEmployeeProject) {
		TEmployeeInfo tEmployeeInfoOld = tEmployeeInfoMapper.selectById(tEmployeeProject.getEmpId());
		TEmployeeProject tEmployeeProjectOld = this.getById(tEmployeeProject.getId());
		if (Common.isNotNull(tEmployeeProject)) {
			TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectById(tEmployeeProject.getEmpId());
			if (tEmployeeProject.getIsLeaveEmployee()== CommonConstants.dingleDigitIntArray[1]) {
				Long count = this.count(Wrappers.<TEmployeeProject>query().lambda()
						.eq(TEmployeeProject::getEmpId,tEmployeeProject.getEmpId())
						.eq(TEmployeeProject::getProjectStatus,CommonConstants.dingleDigitIntArray[0]));
				if (count.compareTo(CommonConstants.DEPT_TREE_ROOT_ID) >0) {
					return R.failed("人员在该项目下存在进行中/未完结的服务");
				}
				tEmployeeInfo.setFileStatus(CommonConstants.dingleDigitIntArray[1]);
				tEmployeeInfoMapper.updateById(tEmployeeInfo);
			}
			tEmployeeProject.setProjectStatus(CommonConstants.dingleDigitIntArray[1]);
			this.updateById(tEmployeeProject);
			tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[0],tEmployeeInfo.getId(),"",tEmployeeProjectOld,tEmployeeInfo);
			tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[1],"",tEmployeeProject.getId(),tEmployeeInfoOld,tEmployeeProject);
			return R.ok();
		}
		return R.failed("传参为空！");
	}

	@Override
	public R<List<ErrorMessage>> batchDeleteEmpPro(List<EmployeeProjectVO> excelVOList, BindingResult bindingResult) {
		// 通用校验获取失败的数据
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();

		// 执行数据插入操作 组装 PostDto
		for (int i = 0; i < excelVOList.size(); i++) {
			EmployeeProjectVO excel = excelVOList.get(i);
			//根据身份证和项目编码获取项目档案
			TEmployeeProject tEmployeeProject = this.getOne(Wrappers.<TEmployeeProject>query().lambda()
					.eq(TEmployeeProject::getEmpIdcard, excel.getEmpIdcard())
					.eq(TEmployeeProject::getDeptNo, excel.getDeptNo())
					.eq(TEmployeeProject::getDeleteFlag, CommonConstants.STATUS_NORMAL));

			TEmployeeInfo tEmployeeInfoOld = tEmployeeInfoMapper.selectById(tEmployeeProject.getEmpId());
			TEmployeeProject tEmployeeProjectOld = this.getById(tEmployeeProject.getId());
			if (Common.isNotNull(tEmployeeProject)) {
				TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectById(tEmployeeProject.getEmpId());
				if (tEmployeeProject.getIsLeaveEmployee() == CommonConstants.dingleDigitIntArray[1]) {
					Long count = this.count(Wrappers.<TEmployeeProject>query().lambda()
							.eq(TEmployeeProject::getEmpId, tEmployeeProject.getEmpId())
							.eq(TEmployeeProject::getProjectStatus, CommonConstants.dingleDigitIntArray[0]));
					if (count.compareTo(CommonConstants.DEPT_TREE_ROOT_ID) > 0) {
						errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.ARCHIVES_PROJECT_CHANGE_NOT_EXIST)));
					}
					tEmployeeInfo.setFileStatus(CommonConstants.dingleDigitIntArray[1]);
					tEmployeeInfoMapper.updateById(tEmployeeInfo);
				}
				tEmployeeProject.setProjectStatus(CommonConstants.dingleDigitIntArray[1]);
				this.updateById(tEmployeeProject);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[0], tEmployeeInfo.getId(), "", tEmployeeProjectOld, tEmployeeInfo);
				tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[1], "", tEmployeeProject.getId(), tEmployeeInfoOld, tEmployeeProject);
			}
		}
		if (errorMessageList.size()> CommonConstants.ZERO_INT) {
			return R.failed(errorMessageList);
		}
		return R.ok();
	}

	@Override
	public R<List<ErrorMessage>> importListAdd(InputStream inputStream,String isAdd) {
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<EmployeeProjectVO> util1 = new ExcelUtil<>(EmployeeProjectVO.class);
		// 写法2：
		// 匿名内部类 不用额外写一个DemoDataListener
		// 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
		try {

			EasyExcel.read(inputStream, EmployeeProjectVO.class, new ReadListener<EmployeeProjectVO>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT;
				/**
				 *临时存储
				 */
				private List<EmployeeProjectVO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

				@Override
				public void invoke(EmployeeProjectVO data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex + 1);
					ErrorMessage errorMessage = util1.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)) {
						errorMessageList.add(errorMessage);
					} else {
						cachedDataList.add(data);
					}
					if (cachedDataList.size() >= BATCH_COUNT) {
						saveData();
						// 存储完成清理 list
						cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
					}
				}

				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					saveData();
				}

				/**
				 * 加上存储数据库
				 */
				private void saveData() {
					log.info("{}条数据，开始存储数据库！", cachedDataList.size());
					importListAdd(cachedDataList, errorMessageList,isAdd);
					log.info("存储数据库成功！");
				}
			}).sheet().doRead();
		} catch (Exception e) {
			log.error(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR, e);
			return R.failed(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR);
		}
		return R.ok(errorMessageList);
	}

	/**
	 * 新增档案操作记录
	 * @param excelVOList
	 * @param errorMessageList
	 * @param
	 * @author huyc
	 * @date 2022-06-20 18:52:16
	 */
	@Transactional
	public void importListAdd(List<EmployeeProjectVO> excelVOList,  List<ErrorMessage> errorMessageList, String idAdd) {
		// 通用校验获取失败的数据
		List<TEmployeeInfo> updateList = new ArrayList();
		List<TEmployeeProject> proInsList = new ArrayList();
		List<TEmployeeProject> proupdateList = new ArrayList();

		// 获取身份证、手机号列表，批量查询档案
		Map<String, Integer> idCardMap = new HashMap<>();
		String idCard;
		String deptNo;

		// 执行数据插入操作 组装 PostDto
		for (int i = 0; i < excelVOList.size(); i++) {
			EmployeeProjectVO excel = excelVOList.get(i);
			Set<String> errorMsg = new HashSet<>();

			idCard = excel.getEmpIdcard();
			deptNo = excel.getDeptNo();
			if (idCardMap.get(idCard.concat(deptNo)) != null) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(),"第" + (excel.getRowIndex()) + "行身份证号+项目编码与第" + idCardMap.get(idCard) + "行重复！"));
			} else {
				idCardMap.put(idCard.concat(deptNo), i + 2);
			}

			//根据身份证获取人员档案
			TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectOne(Wrappers.<TEmployeeInfo>query().lambda()
					.eq(TEmployeeInfo::getEmpIdcard, excel.getEmpIdcard())
					.eq(TEmployeeInfo::getDeleteFlag, CommonConstants.STATUS_NORMAL));
			//根据身份证和项目编码获取项目档案
			TEmployeeProject tEmployeeProject = this.getOne(Wrappers.<TEmployeeProject>query().lambda()
					.eq(TEmployeeProject::getEmpIdcard, excel.getEmpIdcard())
					.eq(TEmployeeProject::getDeptNo, excel.getDeptNo())
					.eq(TEmployeeProject::getDeleteFlag, CommonConstants.STATUS_NORMAL));

			//不存在复档或复项的情况
			//档案无（在档人员、离职库皆无），项目无
			if (Common.isEmpty(tEmployeeInfo) && Common.isEmpty(tEmployeeProject)) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.CHECKS_EXIT_EMPPROJECT_ERROR)));

				//档案有（在档人员），项目无
			} else if (Common.isNotNull(tEmployeeInfo) && Common.isEmpty(tEmployeeProject)
					&& CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()) {
				updateExcelPost(excel, updateList, tEmployeeInfo,CommonConstants.ONE_INT);
				insertExcelPro(excel, proInsList);
				//档案有（在档人员），项目有（草稿/已审核）；
			} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()
					&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[0] == tEmployeeProject.getProjectStatus()) {
				updateExcelPost(excel, updateList, tEmployeeInfo,CommonConstants.ZERO_INT);
				updateExcelPro(excel, proupdateList, tEmployeeProject);
			}

			//存在复档或复项的情况，允许复档复项
			if (CommonConstants.ZERO_STRING.equals(idAdd)) {
				//档案有（离职库），项目（已减档）
				if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
				&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[1] == tEmployeeProject.getProjectStatus()) {
					updateExcelPost(excel, updateList, tEmployeeInfo,CommonConstants.ZERO_INT);
					updateExcelPro(excel, proupdateList, tEmployeeProject);
					//档案有（离职库），项目无；
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
					&& Common.isEmpty(tEmployeeProject) ) {
					updateExcelPost(excel, updateList, tEmployeeInfo,CommonConstants.ONE_INT);
					insertExcelPro(excel, proInsList);
					//档案有（在档人员），项目（已减档）
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()
					&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[1] == tEmployeeProject.getProjectStatus()) {
					updateExcelPost(excel, updateList, tEmployeeInfo,CommonConstants.ZERO_INT);
					updateExcelPro(excel, proupdateList, tEmployeeProject);
				}
				//不允许复档复项
			} else {
				//档案有（离职库），项目（已减档）
				if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
						&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[1] == tEmployeeProject.getProjectStatus()) {
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.CHECKS_EMP_PROJECT_ERROR)));
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
						&& Common.isEmpty(tEmployeeProject)) {
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.CHECKS_REDUCE_EMP_ERROR)));
					//档案有（在档人员），项目（已减档）
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()
						&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[1] == tEmployeeProject.getProjectStatus()){
					errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.CHECKS_REDUCE_PROJECT_ERROR)));		}
			}
		}

		try {
			if (updateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeInfoMapper.updateExcelEmployeeInfo(updateList);
			}
			if (proInsList.size() > CommonConstants.dingleDigitIntArray[0]) {
				baseMapper.insertExcelEmpProject(proInsList);
				List<String> idList = proInsList.stream().map(TEmployeeProject::getEmpIdcard).collect(Collectors.toList());
				List<TEmployeeInfo> updList = tEmployeeInfoMapper.selectList(Wrappers.<TEmployeeInfo>query().lambda().in(TEmployeeInfo::getEmpIdcard,idList));
				baseMapper.updateEmpIdById(updList);
			}
			if (proupdateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				baseMapper.updateExcelEmpProject(proupdateList);
			}
		} catch (Exception e) {
			log.error("数据更新异常",e);
		}
	}

	@Override
	public R<List<ErrorMessage>> importEmpProjectUpdate(InputStream inputStream) {
		List<ErrorMessage> errorMessageList = new ArrayList<>();
		ExcelUtil<EmployeeProjectVO> util1 = new ExcelUtil<>(EmployeeProjectVO.class);;
		// 写法2：
		// 匿名内部类 不用额外写一个DemoDataListener
		// 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
		try {
			EasyExcel.read(inputStream, EmployeeProjectVO.class, new ReadListener<EmployeeProjectVO>() {
				/**
				 * 单次缓存的数据量
				 */
				public static final int BATCH_COUNT = CommonConstants.BATCH_COUNT;
				/**
				 *临时存储
				 */
				private List<EmployeeProjectVO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

				@Override
				public void invoke(EmployeeProjectVO data, AnalysisContext context) {
					ReadRowHolder readRowHolder = context.readRowHolder();
					Integer rowIndex = readRowHolder.getRowIndex();
					data.setRowIndex(rowIndex+1);
					ErrorMessage errorMessage = util1.checkEntity(data, data.getRowIndex());
					if (Common.isNotNull(errorMessage)){
						errorMessageList.add(errorMessage);
					}else {
						cachedDataList.add(data);
					}
					if (cachedDataList.size() >= BATCH_COUNT) {
						saveData();
						// 存储完成清理 list
						cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
					}
				}

				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					saveData();
				}

				/**
				 * 加上存储数据库
				 */
				private void saveData() {
					log.info("{}条数据，开始存储数据库！", cachedDataList.size());
					importEmpProjectUpdate(cachedDataList,errorMessageList);
					log.info("存储数据库成功！");
				}
			}).sheet().doRead();
		}catch (Exception e){
			log.error(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR,e);
			return R.failed(CommonConstants.IMPORT_DATA_ANALYSIS_ERROR);
		}
		return  R.ok(errorMessageList);
	}

	/**
	 * @Author huyc
	 * @Description  批量更新项目档案信息
	 * @Date 19:25 2022/6/21
	 **/
	public void importEmpProjectUpdate(List<EmployeeProjectVO> excelVOList, List<ErrorMessage> errorMessageList) {
		// 通用校验获取失败的数据
		Map<Long,ErrorMessage> errorMsgMap = new HashMap<>();

		List<TEmployeeProject> updateList = new ArrayList<>();

		Map<String, Integer> checkCountMap = new HashMap<>();
		// 执行数据插入操作 组装
		for (int i = 0; i < excelVOList.size(); i++) {
			// 已有验证报错直接下一个
			if (Common.isNotNull(errorMsgMap.get(i + 2))) {
				continue;
			}
			EmployeeProjectVO excel = excelVOList.get(i);

			String checkCount = excel.getEmpIdcard().concat(excel.getDeptNo());
			if (Common.isNotNull(checkCountMap.get(checkCount))) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(),"第" + (excel.getRowIndex()) + "行身份证号+项目编码与第" + checkCountMap.get(checkCount) + "行重复！"));
			} else {
				checkCountMap.put(checkCount, i + 2);
			}
			//根据身份证和项目编码获取项目档案
			TEmployeeProject tEmployeeProject = this.getOne(Wrappers.<TEmployeeProject>query().lambda()
					.eq(TEmployeeProject::getEmpIdcard, excel.getEmpIdcard())
					.eq(TEmployeeProject::getDeptNo, excel.getDeptNo())
					.eq(TEmployeeProject::getDeleteFlag, CommonConstants.STATUS_NORMAL));
			if (Common.isEmpty(tEmployeeProject)) {
				errorMessageList.add(new ErrorMessage(excel.getRowIndex(),MsgUtils.getMessage(ErrorCodes.CHECKS_EMP_EXIT_ERROR)));
			}

			// 数据合法情况
			if (CollUtil.isEmpty(errorMessageList)) {
				updateExcelPro(excel,updateList,tEmployeeProject);
			}
		}
		try {
			if (updateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				baseMapper.updateExcelEmpProject(updateList);
			}
		} catch (Exception e) {
			log.error("数据更新异常",e);
		}
	}

	/**
	 * 插入excel Pro
	 */
	private void insertExcelPro(EmployeeProjectVO excel,List<TEmployeeProject> proInsList) {
		TEmployeeProject insTEmployeePro = new TEmployeeProject();
		BeanUtil.copyProperties(excel, insTEmployeePro);
		insTEmployeePro.setId(String.valueOf(UUID.randomUUID()).replaceAll("-",""));
		insTEmployeePro.setDeleteFlag(CommonConstants.STATUS_NORMAL);
		insTEmployeePro.setStatus(CommonConstants.dingleDigitIntArray[0]);
		//人员档案主表id先设置成空，后面更新id
		insTEmployeePro.setEmpId(CommonConstants.EMPTY_STRING);

		String empNO = getEmpNo(insTEmployeePro.getDeptNo());
		insTEmployeePro.setEmpNo(empNO);
		//员工编码生成规则
		TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectOne(Wrappers.<TEmployeeInfo>query().lambda()
				.eq(TEmployeeInfo::getEmpIdcard, excel.getEmpIdcard())
				.eq(TEmployeeInfo::getDeleteFlag, CommonConstants.STATUS_NORMAL));
		insTEmployeePro.setEmpCode(tEmployeeInfo.getEmpCode());
		YifuUser user = SecurityUtils.getUser();
		insTEmployeePro.setCreateBy(user.getId());
		insTEmployeePro.setCreateName(user.getNickname());
		insTEmployeePro.setProjectSource(CommonConstants.dingleDigitStrArray[5]);
		proInsList.add(insTEmployeePro);
	}

	/**
	 * @param
	 * @Description: 获取员工主码
	 * @Author: hgw
	 * @Date: 2022/6/22 17:52
	 * @return: java.lang.String
	 **/
	private synchronized String getCode() {
		String nowDay = DateUtil.getThisDay();
		Cache cache = cacheManager.getCache(CacheConstants.EVERYDAY_EMP_CODE);
		Object nowNumObj = cache.get(nowDay);
		int nowNums = 1;
		if (Common.isNotNull(nowNumObj)) {
			SimpleValueWrapper value = (SimpleValueWrapper) nowNumObj;
			nowNums = (Integer) value.get() + 1;
		}
		cache.put(nowDay, nowNums);
		return "ZM" + nowDay + this.getFiveNum(String.valueOf(nowNums));
	}

	/**
	 * @param nowNums 数字
	 * @Description: 获取五位字符型数字
	 * @Author: hgw
	 * @Date: 2022/6/21 17:35
	 * @return: 五位字符型数字
	 **/
	private String getFiveNum(String nowNums) {
		if (nowNums.length() >= 5) {
			return nowNums.substring(0, 5);
		}
		String[] zeroArr = {"0", "00", "000", "0000"};
		int num = 4 - nowNums.length();
		return zeroArr[num] + nowNums;
	}

	@Override
	public R<List<ErrorMessage>> batchRemoveByIds(String ids) {
		List<ErrorMessage> errorList = new ArrayList<ErrorMessage>();
		List<String> idsList = null;
		if (!Common.isEmpty(ids)) {
			idsList = Common.initStrToList(ids, CommonConstants.COMMA_STRING);
		} else {
			return R.failed(ErrorCodes.PARAM_NOT_EMPTY);
		}
		List<TEmployeeProject> list = new ArrayList<>();
		if (Common.isNotEmpty(idsList)) {
			list = baseMapper.selectList(Wrappers.<TEmployeeProject>query().lambda().in(TEmployeeProject::getId, idsList));
		}
		if(Common.isNotEmpty(list)) {
			int i = 0;
			for (TEmployeeProject delProject : list) {
				++i;
				try {
					if (CommonConstants.dingleDigitIntArray[0] ==delProject.getStatus()) {
						delProject.setDeleteFlag(CommonConstants.ONE_STRING);
						baseMapper.updateById(delProject);
					}else {
						errorList.add(new ErrorMessage(i,MsgUtils.getMessage(ErrorCodes.CHECKS_PROJECT_DELETE_ERROR)));
					}
				} catch (Exception e) {
					log.error("项目档案批量删除异常：" + e.getMessage());
					errorList.add(new ErrorMessage(i,MsgUtils.getMessage("项目档案批量删除异常：", e.getMessage())));
					return R.failed(errorList,CommonConstants.RESULT_DATA_FAIL);
				}
			}
		}
		if (CollUtil.isNotEmpty(errorList)) {
			return R.failed(errorList);
		}
		return R.ok();
	}

	@Override
	public IPage<TEmployeeProject> getTEmployeeProjectInfoPage(Page page, TEmployeeProject tEmployeeProject) {
		return baseMapper.getTEmployeeProjectInfoPage(page,tEmployeeProject);
	}


	/**
	 * @Author huyc
	 * @Description  批量导出项目档案信息
	 * @Date 10:55 2022/6/23
	 **/
	@Override
	public void listExportProject(HttpServletResponse response, EmployeeProjectExportVO projectDTO, String idstr, List<String> exportFields) {

		String fileName = "项目档案批量导出" + LocalDateTime.now() + ".xlsx";
		// 根据用户传入确定要导出的字段
		Set<String> includeColumnFiledNames = new HashSet<String>();
		for (String exportField : exportFields) {
			includeColumnFiledNames.add(exportField);
		}

		//获取要导出的列表
		List<EmployeeProjectExportVO> list = new ArrayList<>();

		//获取记录
		list = gettEmpProInfoExportVos(idstr, projectDTO);

		if (Common.isNotNull(list)){
			ExcelUtil<EmployeeProjectExportVO> util = new ExcelUtil<>(EmployeeProjectExportVO.class);
			for (EmployeeProjectExportVO vo:list){
				util.convertEntity(vo,null,null,null);
			}
		}

		ServletOutputStream out = null;
		try {
			if (list.size()>0) {
				out = response.getOutputStream();
				response.setContentType("multipart/form-data");
				response.setCharacterEncoding("utf-8");
				response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + URLEncoder.encode(fileName  , "UTF-8"));
				// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
				EasyExcel.write(out, EmployeeProjectExportVO.class).includeColumnFiledNames(includeColumnFiledNames).sheet("项目档案")
						.doWrite(list);
				out.flush();
			}
		}catch (Exception e){
			log.error("执行异常" ,e);
		}finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	/**
	 * @param employeeInfo
	 * @Description: 新增项目档案
	 * @Author: huyc
	 * @Date: 2022/6/23 18:06
	 **/
	@Override
	public void saveEmployeeProjectInfo(TEmployeeInfo employeeInfo) {
		TEmployeeProject tEmployeeProject = new TEmployeeProject();
		tEmployeeProject.setEmpId(employeeInfo.getId());
		tEmployeeProject.setEmpCode(employeeInfo.getEmpCode());
		tEmployeeProject.setEmpNatrue(employeeInfo.getEmpNatrue());
		tEmployeeProject.setEmpName(employeeInfo.getEmpName());
		tEmployeeProject.setEmpIdcard(employeeInfo.getEmpIdcard());
		tEmployeeProject.setPost(employeeInfo.getPost());
		tEmployeeProject.setProjectSource(CommonConstants.dingleDigitStrArray[4]);

		String empNO = getEmpNo(employeeInfo.getDeptNo());
		tEmployeeProject.setEmpNo(empNO);
		tEmployeeProject.setDeptNo(employeeInfo.getDeptNo());

		TSettleDomain tSettleDomain = tSettleDomainService.getOne(Wrappers.<TSettleDomain>query().lambda()
				.eq(TSettleDomain::getDepartNo,employeeInfo.getDeptNo()).eq(TSettleDomain::getDeleteFlag,CommonConstants.STATUS_NORMAL));
		if (Common.isNotNull(tSettleDomain)) {
			tEmployeeProject.setDeptId(tSettleDomain.getId());
			tEmployeeProject.setDeptName(tSettleDomain.getDepartName());
			TCustomerInfo tCustomerInfo = tCustomerInfoMapper.selectById(tSettleDomain.getCustomerId());
			if(Common.isNotNull(tCustomerInfo)) {;
				tEmployeeProject.setUnitId(tCustomerInfo.getId());
				tEmployeeProject.setUnitNo(tCustomerInfo.getCustomerCode());
				tEmployeeProject.setUnitName(tCustomerInfo.getCustomerName());
			}
		}
		baseMapper.insert(tEmployeeProject);
	}

	/**
	 * 获取导出的项目档案列表
	 */
	private List<EmployeeProjectExportVO> gettEmpProInfoExportVos(String idstr,EmployeeProjectExportVO projectDTO) {
		List<EmployeeProjectExportVO> list;
		if (!Common.isEmpty(idstr)) {
			projectDTO.setIdList(Common.initStrToList(idstr, CommonConstants.COMMA_STRING));
		}
		list = baseMapper.getTEmployeeProjectExportPage(projectDTO);
		return list;
	}

	/**
	 * 更新人员档案
	 */
	private void updateExcelPost(EmployeeProjectVO excel,List<TEmployeeInfo> updateList,TEmployeeInfo tEmployeeInfo,int num) {
		BeanUtil.copyProperties(excel, tEmployeeInfo);
		YifuUser user = SecurityUtils.getUser();
		tEmployeeInfo.setUpdateBy(user.getId());
		if (num == CommonConstants.ONE_INT) {
			tEmployeeInfo.setProjectNum(tEmployeeInfo.getProjectNum().intValue() + CommonConstants.ONE_INT);
		}
		updateList.add(tEmployeeInfo);
		// 记录变更日志
		TEmployeeInfo tEmployeeInfoOld = tEmployeeInfoMapper.selectById(tEmployeeInfo.getId());
		tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[0], tEmployeeInfo.getId(), "", tEmployeeInfoOld, tEmployeeInfo);
	}

	/**
	 * 更新项目档案
	 */
	private void updateExcelPro(EmployeeProjectVO excel,List<TEmployeeProject> proupdateList,TEmployeeProject tEmployeeProject) {
		BeanUtil.copyProperties(excel, tEmployeeProject);
		YifuUser user = SecurityUtils.getUser();
		tEmployeeProject.setUpdateBy(user.getId());
		proupdateList.add(tEmployeeProject);
		// 记录变更日志
		TEmployeeProject tEmployeeProjectOld = this.getById(tEmployeeProject.getId());
		tEmployeeLogService.saveModificationRecord(CommonConstants.dingleDigitIntArray[1], "", tEmployeeProject.getId(), tEmployeeProjectOld, tEmployeeProject);
	}

	@Override
	public List<TEmployeeProject> getListByEmpId(String empId, int projectStatus) {
		TEmployeeProject project = new TEmployeeProject();
		project.setEmpId(empId);
		if (projectStatus == 0) {
			project.setProjectStatus(CommonConstants.ZERO_INT);
		}
		project.setDeleteFlag(CommonConstants.STATUS_NORMAL);
		return this.list(Wrappers.query(project));
	}

	@Override
	public List<TEmployeeProject> getListByEmpIdAndDeptNo(String empId, String deptNo) {
		TEmployeeProject project = new TEmployeeProject();
		project.setEmpId(empId);
		project.setDeptNo(deptNo);
		project.setDeleteFlag(CommonConstants.STATUS_NORMAL);
		return this.list(Wrappers.query(project));
	}

	@Override
	public R getItemByEmpNo(String empIdcard, String empNo) {
		TSettleDomain tSettleDomain = tSettleDomainService.getOne(Wrappers.<TSettleDomain>query().lambda()
				.eq(TSettleDomain::getDepartNo,empNo));
		TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectOne(Wrappers.<TEmployeeInfo>query().lambda()
				.eq(TEmployeeInfo::getEmpIdcard,empIdcard));
		Map<String,Object> map = new HashMap<>();
		String empCode = "";
		if (Common.isNotNull(tEmployeeInfo)) {
			empCode = tEmployeeInfo.getEmpCode();
		}
		String customerName = "";
		if (Common.isNotNull(tSettleDomain)) {
			TCustomerInfo tCustomerInfo = tCustomerInfoMapper.selectOne(Wrappers.<TCustomerInfo>query().lambda()
					.eq(TCustomerInfo::getId,tSettleDomain.getCustomerId()));
			if (Common.isNotNull(tCustomerInfo)) {
				customerName = tCustomerInfo.getCustomerName();
			}
		}
		map.put("empCode",empCode);
		map.put("itemInfo",tSettleDomain);
		map.put("customerName",customerName);
		return R.ok(map);
	}

	@Override
	public R<Map<String, String>> getProjectByIdCard(String empIdCard) {
		List<TEmployeeProject>  projects = baseMapper.selectList(Wrappers.<TEmployeeProject>query().lambda()
				.eq(TEmployeeProject::getDeleteFlag,CommonConstants.ZERO_STRING)
				.eq(TEmployeeProject::getProjectStatus,CommonConstants.ZERO_STRING)
				.eq(TEmployeeProject::getEmpIdcard,empIdCard));
		Map<String,String> projectMap = new HashMap<>();
		if (Common.isNotNull(projects)){
			for (TEmployeeProject project:projects){
				projectMap.put(project.getDeptName(),project.getDeptNo());
			}
		}
		return R.ok(projectMap);
	}

	//获取员工编码
	public String getEmpNo(String deptNo) {
		String str = "";
		String EmpNo = baseMapper.findEmployeeMaxOnlyNoByDepId(deptNo);
		if (!Common.isEmpty(EmpNo)) {
			str = NoUtil.productionNo(EmpNo, CommonConstants.EMPLOYEE_INIT_NO_START);
		} else {
			str = deptNo + CommonConstants.EMPLOYEE_INIT_NO;
		}
		return str;
	}
}
