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

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.AreaMap;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.*;
import com.yifu.cloud.plus.v1.yifu.archives.service.*;
import com.yifu.cloud.plus.v1.yifu.archives.utils.ExcelStyle;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.*;
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.DaprUpmsProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.HttpDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.salary.vo.ExportErrorVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.compress.utils.Lists;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 档案完整度监控
 *
 * @author huyc
 * @date 2024-06-17 16:08:58
 */
@Log4j2
@Service
@RequiredArgsConstructor
@EnableConfigurationProperties({DaprUpmsProperties.class})
public class TCompleteMonitorServiceImpl extends ServiceImpl<TCompleteMonitorMapper, TCompleteMonitor> implements TCompleteMonitorService {

	private final TEmployeeProjectMapper projectMapper;
	private final DaprUpmsProperties daprUpmsProperties;

	// 档案相关服务：
	// 员工不良记录表
	private final TEmpBadRecordService tEmpBadRecordService;
	// 员工工作履历信息表
	private final TEmpWorkRecordingService tEmpWorkRecordingService;
	// 紧急联络人
	private final TEmpContactInfoService tEmpContactInfoService;
	// 员工伤残信息表
	private final TEmpDisabilityInfoService tEmpDisabilityInfoService;
	// 员工学历信息表
	private final TEmpEducationService tEmpEducationService;
	// 员工家庭信息表
	private final TEmpFamilyService tEmpFamilyService;
	// 人员档案表
	private final TEmployeeInfoMapper tEmployeeInfoMapper;
	// 项目档案表
	private final TEmployeeProjectService tEmployeeProjectService;
	// 员工职业资格信息表
	private final TEmpProfessionalQualificationService tEmpProfessionalQualificationService;
	// 附件21（预入职申明签名）；22（预入职确认签名）；23（预入职pdf文件)
	private final TAttaInfoService tAttaInfoService;

	private final TArchivesExportLimitMapper tArchivesExportLimitMapper;

	private final TArchivesLimitMapper tArchivesLimitMapper;

	// 完整度监控配置
	private final TCompleteMonitorSetMapper tCompleteMonitorSetMapper;
	private final TCompleteMonitorSetBaseInfoMapper tCompleteMonitorSetBaseInfoMapper;

	private final OSSUtil ossUtil;

	private final AtomicInteger atomicInteger = new AtomicInteger(0);

	private final TSettleDomainService tSettleDomainService;

	/**
     * 档案完整度监控简单分页查询
     * @param tCompleteMonitor 档案完整度监控
     * @return
     */
    @Override
    public IPage<TCompleteMonitor> getTCompleteMonitorPage(Page<TCompleteMonitor> page, TCompleteMonitorSearchVo tCompleteMonitor){
        return baseMapper.getTCompleteMonitorPage(page,tCompleteMonitor);
    }

	/**
	 * 入职待完善简单分页查询
	 * @param preSearchVo 入职待完善
	 * @return
	 */
	@Override
	public IPage<EmployeeRegistrationProjectListVo> getAllLackArchivesPage(Page<EmployeeRegistrationProjectListVo> page, EmployeeRegistrationPreSearchVo preSearchVo){
		//权限赋值
		initSearchVo(preSearchVo);
		return baseMapper.getAllLackArchivesPage(page,preSearchVo);
	}

    /**
     * 档案完整度监控批量导出
     * @param searchVo 档案完整度监控
     * @return
     */
    @Override
    public void listExport(HttpServletResponse response, TCompleteMonitorSearchVo searchVo){
        String fileName = "档案完整度监控列表" + DateUtil.getThisTime() + ".xlsx";
        //获取要导出的列表
        List<TCompleteMonitorVo> list = new ArrayList<>();
        long count = baseMapper.getExportCount(searchVo);
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
            response.setCharacterEncoding("utf-8");
            response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName  , CommonConstants.UTF8));
            // 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
            //EasyExcel.write(out, TEmpBadRecord.class).sheet("不良记录").doWrite(list);
            ExcelWriter excelWriter = EasyExcel.write(out, TCompleteMonitorVo.class).build();
            int index = 0;
            if (count >  CommonConstants.ZERO_INT){
                for (int i = 0; i <= count; ) {
                    // 获取实际记录
                    searchVo.setLimitStart(i);
                    searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
                    list = baseMapper.getTCompleteMonitorExportList(searchVo);
                    if (Common.isNotNull(list)){
                        ExcelUtil<TCompleteMonitorVo> util = new ExcelUtil<>(TCompleteMonitorVo.class);
                        for (TCompleteMonitorVo vo:list){
                            util.convertEntity(vo,null,null,null);
                        }
                    }
                    if (Common.isNotNull(list)){
                        WriteSheet writeSheet = EasyExcel.writerSheet("档案完整度监控列表"+index).build();
                        excelWriter.write(list,writeSheet);
                        index++;
                    }
                    i = i + CommonConstants.EXCEL_EXPORT_LIMIT;
                    if (Common.isNotNull(list)){
                        list.clear();
                    }
                }
            }else {
                WriteSheet writeSheet = EasyExcel.writerSheet("档案完整度监控列表"+index).build();
                excelWriter.write(list,writeSheet);
            }
            if (Common.isNotNull(list)){
                list.clear();
            }
            out.flush();
            excelWriter.finish();
        }catch (Exception e){
            log.error("执行异常" ,e);
        }finally {
            try {
                if (null != out) {
                    out.close();
                }
            } catch (IOException e) {
                log.error("执行异常", e);
            }
        }
    }

	/**
	 * 档案待完整批量导出
	 * @param searchVo 档案待完整
	 * @return
	 */
	@Override
	public void archivesExport(HttpServletResponse response, EmployeeRegistrationPreSearchVo searchVo){
		String fileName = "档案待完整列表" + DateUtil.getThisTime() + ".xlsx";
		//获取要导出的列表
		List<EmployeeRegistrationProjectListVo> list = new ArrayList<>();
		//权限赋值
		initSearchVo(searchVo);
		long count = baseMapper.getAllLackArchivesExportCount(searchVo);
		try (ServletOutputStream out= response.getOutputStream();){
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName  , CommonConstants.UTF8));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelUtil<EmployeeRegistrationProjectListVo> util = new ExcelUtil<>(EmployeeRegistrationProjectListVo.class);
			// 获取所有字典type
			Map<String,String> nameAndDicTypeMap = util.getConverterDicType();
			// 获取所有字典对应的值
			Map<String,String> redisLabelMap = (Map<String, String>) RedisUtil.redis.opsForValue().get(CacheConstants.REDIS_DICT_LABLE);
			Set<String> exportFields = new HashSet<>(Arrays.asList("deptName", "deptNo", "employeeName", "empIdcard",
					"empPhone", "joinLeaveDate", "empNature", "contractType", "customerUsernameNew", "dataSource",
					"type", "processStatus"));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcel.write(out, EmployeeRegistrationProjectListVo.class)
					.registerConverter(new DictConverter(nameAndDicTypeMap,redisLabelMap))
					.includeColumnFieldNames(exportFields).build();
			int index = 0;
			if (count >  CommonConstants.ZERO_INT){
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.getAllLackArchivesExportList(searchVo);
					if (Common.isNotNull(list)){
						WriteSheet writeSheet = EasyExcel.writerSheet("档案待完整列表"+index).build();
						excelWriter.write(list,writeSheet);
						index++;
					}
					if (Common.isNotNull(list)){
						list.clear();
					}
				}
			}else {
				WriteSheet writeSheet = EasyExcel.writerSheet("档案待完整列表"+index).build();
				excelWriter.write(list,writeSheet);
			}
			if (Common.isNotNull(list)){
				list.clear();
			}
			excelWriter.finish();
		}catch (Exception e){
			log.error("执行异常" ,e);
		}
	}

	@Override
	public void createComlpeteMonitor() {
		//先删除所有的档案监控数据
		baseMapper.deleteAllMonitorInfo();
		//批量查询项目档案的是否完整状态
		/*List<TCompleteMonitorFlagVo> flagList = baseMapper.checkEmpProjectCompleteFlag(null);
		if (!flagList.isEmpty()) {
			List<String> projectIdList = new ArrayList<>();
			List<String> projectNotIdList = new ArrayList<>();
			String projectId;
			for(TCompleteMonitorFlagVo flagVo : flagList) {
				boolean flag = checkObjFieldIsNull(flagVo);
				projectId = flagVo.getEmpProjectId();
				if(!flag){
					projectIdList.add(projectId);
				} else {
					projectNotIdList.add(projectId);
				}
			}
			//批量更新
			if (!projectIdList.isEmpty()) {
				projectMapper.batchUpdateEmpProjectCompleteStatus(projectIdList, CommonConstants.ZERO_STRING);
			}
			//批量更新-不完整
			if (!projectIdList.isEmpty()) {
				projectMapper.batchUpdateEmpProjectCompleteStatus(projectNotIdList, CommonConstants.ONE_STRING);
			}
		}*/
		this.judgeProjectCompleteCore(null);

		//查询项目维度的信息
		List<TCompleteMonitor> list = baseMapper.getAllMonitorEmpList(null);
		//查询当天新增的项目档案数据来筛选需要刷新的数据
		this.saveBatch(list);
	}

	/**
	 * 档案完整度监控简单分页查询
	 * @param completeMonitorInfoVo
	 * @return
	 */
	@Override
	public IPage<TCompleteMonitorInfoVo> getMonitorEmpInfoListPage(Page<TCompleteMonitorInfoVo> page, TCompleteMonitorInfoVo completeMonitorInfoVo){
		return baseMapper.getMonitorEmpInfoList(page,completeMonitorInfoVo);
	}

	@Override
	public void updateProjectStatusByDeptNo(String deptNo) throws IllegalAccessException{

		//批量查询项目档案的是否完整状态
		/*List<TCompleteMonitorFlagVo> flagList = baseMapper.checkEmpProjectCompleteFlag(deptNo);
		if (!flagList.isEmpty()) {
			List<String> projectIdList = new ArrayList<>();
			List<String> projectNotIdList = new ArrayList<>();
			String projectId;
			for(TCompleteMonitorFlagVo flagVo : flagList) {
				boolean flag = checkObjFieldIsNull(flagVo);
				projectId = flagVo.getEmpProjectId();
				if(!flag){
					projectIdList.add(projectId);
				} else {
					projectNotIdList.add(projectId);
				}
			}
			//批量更新
			if (!projectIdList.isEmpty()) {
				projectMapper.batchUpdateEmpProjectCompleteStatus(projectIdList, CommonConstants.ZERO_STRING);
			}
			if (!projectNotIdList.isEmpty()) {
				projectMapper.batchUpdateEmpProjectCompleteStatus(projectNotIdList, CommonConstants.ONE_STRING);
			}
		}*/
		this.judgeProjectCompleteCore(deptNo);

		//删除项目监控表数据
		baseMapper.deleteMonitorInfoByDeptNo(deptNo);
		//查询项目维度的信息
		List<TCompleteMonitor> list = baseMapper.getAllMonitorEmpList(deptNo);
		//查询当天新增的项目档案数据来筛选需要刷新的数据
		this.saveBatch(list);
	}

	/**
	 * @param deptNo 项目编码
	 * @Description:
	 * @Author: hgw
	 * @Date: 2025/2/25 15:30
	 * @return: void
	 **/
	private void judgeProjectCompleteCore(String deptNo) {

		// 1：员工类型为代理的 直接完整
		projectMapper.updateTrueCompleteByAgent();

		// 查询需要判断的数量有多少
		List<String> typeList = projectMapper.getNeedJudgeCompleteType(deptNo);
		if (typeList != null && !typeList.isEmpty()) {
			// 查找配置
			List<TCompleteMonitorSet> setList = tCompleteMonitorSetMapper.getAllList();
			Map<String, String> setMap = new HashMap<>();
			if (setList != null && !setList.isEmpty()) {
				String[] strArr;
				String baseId;
				for (TCompleteMonitorSet set:setList) {
					strArr = set.getContractType().split(",");
					baseId = set.getBaseId();
					for (String str : strArr) {
						setMap.put(str, baseId);
					}
				}
			}
			// 默认配置
			String baseSet = setMap.get("-1");
			List<TCompleteMonitorSetBaseInfo> baseSetList = tCompleteMonitorSetBaseInfoMapper.getBaseInfoByIds(baseSet);
			Map<String, List<TCompleteMonitorSetBaseInfo>> baseSetMap = new HashMap<>();
			baseSetMap.put(baseSet, baseSetList);
			// 表示有了其他配置
			if (setMap.size() > 1) {
				String useSet;
				for (String type : typeList) {
					useSet = setMap.get(type);
					if (Common.isEmpty(useSet)) {
						useSet = baseSet;
					}
					if ("-1".equals(useSet)) {
						// -1表示配置的为空，直接完整
						projectMapper.batchUpdateEmpProjectCompleteStatusByType(type, deptNo);
					} else {
						baseSetList = baseSetMap.get(useSet);
						if (baseSetList == null) {
							baseSetList = tCompleteMonitorSetBaseInfoMapper.getBaseInfoByIds(useSet);
							baseSetMap.put(useSet, baseSetList);
						}
						doJudgeCore(type, deptNo, baseSetList);
					}
				}
			} else {
				// 表示都用默认配置
				doJudgeCore(null, deptNo, baseSetList);
			}

		}
	}

	/**
	 * @param type 合同类型
	 * @param deptNo 项目编码
	 * @param baseSetList 配置list
	 * @Description: 核心配置
	 * @Author: hgw
	 * @Date: 2025/2/26 17:45
	 * @return: void
	 **/
	private void doJudgeCore(String type, String deptNo, List<TCompleteMonitorSetBaseInfo> baseSetList) {
		List<String> empProjectId;
		if (baseSetList != null && !baseSetList.isEmpty()) {
			empProjectId = null;
			String tableInfo;
			for (TCompleteMonitorSetBaseInfo baseInfo : baseSetList) {
				tableInfo = baseInfo.getBaseTable();
				if ("t_employee_info".equals(tableInfo) || "t_employee_project".equals(tableInfo)) {
					tableInfo = null;
				}
				// 根据配置，逐个查询是否有空值：
				empProjectId = projectMapper.getNeedNextJudgeCompleteByColumnAndEmpProjectId(
						type, deptNo, baseInfo.getBaseColumn(), tableInfo, empProjectId);
				if (empProjectId == null || empProjectId.isEmpty()) {
					break;
				}
			}
			// 这些事经过筛选的项目id，表示完整
			if (empProjectId != null && !empProjectId.isEmpty()) {
				projectMapper.batchUpdateEmpProjectCompleteStatus(empProjectId, CommonConstants.ZERO_STRING);
			}
		}
	}

	/**
	 *
	 * @param obj 对象
//	 * @param checkField  要检查的属性集合
	 * @return  true 指定属性有为空的   false  所有属性值都不为空
	 * @throws IllegalAccessException
	 */
	public boolean checkObjFieldIsNull(Object obj) throws IllegalAccessException {
		//获取对象的类
		Class<?> aClass = obj.getClass();
		Field[] declaredFields = aClass.getDeclaredFields();
		//筛选出包含在要检查的list 并且 属性为null的字段
		for(Field field : declaredFields){
			if (null == field.get(obj)) {
				return true;
			}
		}
		return false;
	}

	private Set<String> getExportFieldNameDetailByClass(Class<?> clazz) {
		Set<String> exportfieldsName = new HashSet<>();
		Field[] fields = clazz.getDeclaredFields();
		ExcelAttribute annotation;
		for (Field field : fields) {
			annotation = field.getAnnotation(ExcelAttribute.class);
			if (annotation != null && Common.isNotNull(annotation.name()) && annotation.needExport()) {
				exportfieldsName.add(field.getName());
			}
		}
		return exportfieldsName;
	}

	@Override
	public void exportAll(HttpServletResponse response, TCompleteMonitorSearchVo searchVo) {
		TArchivesLimit archivesLimit = tArchivesLimitMapper.selectById(CommonConstants.FOUR_INT);
		Integer maxLimit = 2;
		if (Common.isNotNull(archivesLimit) && Common.isNotNull(archivesLimit.getMaxNum())) {
			maxLimit = archivesLimit.getMaxNum();
		}
		if (atomicInteger.incrementAndGet() <= maxLimit) {
			try {
				exportAllCore(response, searchVo);
			} catch (Exception e) {
				log.error("导出异常：", e);
			} finally {
				atomicInteger.decrementAndGet();
			}
		} else {
			// 前面做了+1（atomicInteger.incrementAndGet()）这里也要-1
			atomicInteger.decrementAndGet();
			log.error("档案完整度监控导出超出阈值：" + ResultConstants.FILE_DOWN_LOAD_DATA);
			exportError(response, ResultConstants.FILE_DOWN_LOAD_DATA);
		}
	}

	@Override
	public void exportError(HttpServletResponse response, String errorMessage) {
		String fileName = "导出异常" + DateUtil.getThisTime() + CommonConstants.XLSX;
		//获取要导出的列表
		List<ExportErrorVo> list = new ArrayList<>();
		list.add(new ExportErrorVo(errorMessage));
		ServletOutputStream out = null;
		try {
			out = response.getOutputStream();
			response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
			response.setCharacterEncoding("utf-8");
			response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, "UTF-8"));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcelFactory.write(out, ExportErrorVo.class).build();
			int index = 0;
			WriteSheet writeSheet = EasyExcelFactory.writerSheet("异常信息" + index).build();
			excelWriter.write(list, writeSheet);
			if (Common.isNotNull(list)) {
				list.clear();
			}
			out.flush();
			excelWriter.finish();
		} catch (Exception e) {
			log.error("执行异常", e);
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("执行异常", e);
			}
		}
	}

	/**
	 * 预入职导出全量
	 *
	 * @return
	 */
	private void exportAllCore(HttpServletResponse response, TCompleteMonitorSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		if (user != null) {
			TArchivesExportLimit exportLimit = new TArchivesExportLimit();
			exportLimit.setType(CommonConstants.TWO_INT);
			exportLimit.setCreateBy(user.getId());
			String name = "档案完整度监控详情";
			String fileName = name + DateUtil.getThisTime() + ".xlsx";
			//获取要导出的列表
			List<TMainExportAllVO> list = Lists.newArrayList();
			long count = baseMapper.getTEmpMainAllCount(searchVo);
			ServletOutputStream out = null;
			try {
				out = response.getOutputStream();
				response.setContentType(CommonConstants.MULTIPART_FORM_DATA);
				response.setCharacterEncoding("utf-8");
				response.setHeader(CommonConstants.CONTENT_DISPOSITION, CommonConstants.ATTACHMENT_FILENAME + URLEncoder.encode(fileName, CommonConstants.UTF8));
				ExcelWriter excelWriter = null;
				if (count > 200000) {
					exportError(response, "数据超过20万条，请联系管理员后端导出");
				} else {
					exportLimit.setDeleteFlag(CommonConstants.ZERO_INT);
					exportLimit.setCreateName(user.getNickname());
					exportLimit.setCreateTime(LocalDateTime.now());
					tArchivesExportLimitMapper.insert(exportLimit);

					// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
					List<List<String>> headList = Lists.newArrayList();
					headList.add(this.getNewArrayList(new String[]{"信息是否完整", "信息是否完整"}));
					headList.add(this.getNewArrayList(new String[]{"进项目时间", "进项目时间"}));
					String oneTitle = "员工基本信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "员工主码"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "员工类型"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "员工姓名"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "身份证号"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "性别"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "身份证期限"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "身份证开始日期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "身份证截止日期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "出生日期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "年龄"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "婚姻状况"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "民族"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "政治面貌"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "手机号码"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "邮箱"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "微信号"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "户籍所在地-省"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "户籍所在地-市"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "户籍所在地-区/县"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "户口性质"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "档案所在地-省"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "档案所在地-市"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "档案所在地-区/县"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "档案状态"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "通信地址"}));
					oneTitle = "在项信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "客户名称"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "项目名称"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "项目编码"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "业务类型"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "合同类型"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "工时制"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "就职岗位"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "入职日期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "试用期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "标签"}));
					oneTitle = "紧急联络人";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "姓名"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "与本人关系"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "联系地址"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "联系电话"}));
					oneTitle = "最高教育经历";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "学校"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "专业"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "学历"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否大专及以上"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "最高学历"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "入学时间"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "毕业时间"}));
					oneTitle = "主要工作经历";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否为首份工作"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "工作单位"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "工作岗位"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "开始工作日期"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "结束工作日期"}));
					oneTitle = "主要家庭成员信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "成员姓名"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "与本人关系"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "手机号码"}));
					oneTitle = "职业资格信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否有职业资格证书"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "申报年度"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "职业资格名称"}));
					oneTitle = "伤残信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否曾被认定为工伤"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否有职业病"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "职业病名称"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否有传染性疾病"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "传染病名称"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否持有残疾人证明"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "伤残病名称"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "伤残等级"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "是否从事过井下、高空、高温、特别繁重体力劳动以及有毒有害工种"}));
					oneTitle = "不良记录";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "不良记录描述"}));
					oneTitle = "银行卡信息";
					headList.add(this.getNewArrayList(new String[]{oneTitle, "银行卡号"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "开户总行"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "开户省"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "开户市"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "开户支行"}));
					headList.add(this.getNewArrayList(new String[]{oneTitle, "计税月份"}));

					Set<String> titleContent = getExportFieldNameDetailByClass(TMainExportAllVO.class);
					//ExcelUtil<TMainExportAllVO> util = new ExcelUtil<>(TMainExportAllVO.class)
					// 获取所有字典type
					Map<String,String> nameAndDicTypeMap = getConverterDicTypeAndArea(TMainExportAllVO.class);
					// 获取所有字典对应的值
					Map<String,String> redisLabelMap = (Map<String, String>) RedisUtil.redis.opsForValue().get(CacheConstants.REDIS_DICT_LABLE);
					Map<String,String> idLabelMap = (Map<String, String>) RedisUtil.redis.opsForValue().get(CacheConstants.AREA_VALUE_ALL);
					if (Common.isEmpty(idLabelMap) || idLabelMap.isEmpty()) {
						R<AreaMap> areaListR = HttpDaprUtil.invokeMethodPost(daprUpmsProperties.getAppUrl(), daprUpmsProperties.getAppId(), "/area/inner/getAreaMapAll", "", AreaMap.class, SecurityConstants.FROM_IN);
						if (Common.isNotNull(areaListR)) {
							idLabelMap = areaListR.getData().getIdLabelMap();
						}
					}
					if (redisLabelMap != null && idLabelMap != null) {
						redisLabelMap.putAll(idLabelMap);
					}
					excelWriter = EasyExcelFactory.write(out).registerWriteHandler(ExcelStyle.getNormalStype())
							.registerConverter(new DictConverter(nameAndDicTypeMap, redisLabelMap))
							.includeColumnFieldNames(titleContent).head(headList).build();

					int index = 1;
					if (count > CommonConstants.ZERO_INT) {
						int limitNum = 10000;
						ExcelWriterSheetBuilder writeSheet;
						List<TMainExportAllVO> listWork;
						Map<String, TMainExportAllVO> mapWork;
//						List<TMainExportAllVO> listContract;
//						Map<String, TMainExportAllVO> mapContract;
						List<TMainExportAllVO> listEducation;
						Map<String, TMainExportAllVO> mapEducation;
						List<TMainExportAllVO> listBad;
						Map<String, TMainExportAllVO> mapBad;
						List<TMainExportAllVO> listDisability;
						Map<String, TMainExportAllVO> mapDisability;
						List<TMainExportAllVO> listFamily;
						Map<String, TMainExportAllVO> mapFamily;
						List<TMainExportAllVO> listProfessional;
						Map<String, TMainExportAllVO> mapProfessional;
						TMainExportAllVO temp;

						List<String> empIdList;
						for (int i = 0; i <= count; i += limitNum) {
							exportLimit.setProgressBar("导出完整度进度："+i+"/"+count);
							tArchivesExportLimitMapper.updateById(exportLimit);
							empIdList = new ArrayList<>();
							// 获取实际记录
							searchVo.setLimitStart(i);
							searchVo.setLimitEnd(limitNum);
							list = baseMapper.getTEmpMainAllList(searchVo);
							if (list != null && !list.isEmpty()) {
								for (TMainExportAllVO vo : list) {
									empIdList.add(vo.getMainId());
								}
//								listContract = baseMapper.getTEmpMainAllListByContract(empIdList);
								listEducation = baseMapper.getTEmpMainAllListByEducation(empIdList);
								listBad = baseMapper.getTEmpMainAllListByBad(empIdList);
								listDisability = baseMapper.getTEmpMainAllListByDisability(empIdList);
								listWork = baseMapper.getTEmpMainAllListByWork(empIdList);
								listFamily = baseMapper.getTEmpMainAllListByFamily(empIdList);
								listProfessional = baseMapper.getTEmpMainAllListByProfessional(empIdList);
//								mapContract = new HashMap<>();
								mapEducation = new HashMap<>();
								mapBad = new HashMap<>();
								mapDisability = new HashMap<>();
								mapWork = new HashMap<>();
								mapFamily = new HashMap<>();
								mapProfessional = new HashMap<>();
//								if (listContract != null && !listContract.isEmpty()) {
//									for (TMainExportAllVO vo : listContract) {
//										mapContract.putIfAbsent(vo.getMainId(), vo);
//									}
//								}
								if (listEducation != null && !listEducation.isEmpty()) {
									for (TMainExportAllVO vo : listEducation) {
										mapEducation.putIfAbsent(vo.getMainId(), vo);
									}
								}
								if (listBad != null && !listBad.isEmpty()) {
									for (TMainExportAllVO vo : listBad) {
										mapBad.putIfAbsent(vo.getMainId(), vo);
									}
								}
								if (listDisability != null && !listDisability.isEmpty()) {
									for (TMainExportAllVO vo : listDisability) {
										mapDisability.putIfAbsent(vo.getMainId(), vo);
									}
								}
								if (listWork != null && !listWork.isEmpty()) {
									for (TMainExportAllVO vo : listWork) {
										mapWork.putIfAbsent(vo.getMainId(), vo);
									}
								}
								if (listFamily != null && !listFamily.isEmpty()) {
									for (TMainExportAllVO vo : listFamily) {
										mapFamily.putIfAbsent(vo.getMainId(), vo);
									}
								}
								if (listProfessional != null && !listProfessional.isEmpty()) {
									for (TMainExportAllVO vo : listProfessional) {
										mapProfessional.putIfAbsent(vo.getMainId(), vo);
									}
								}
								for (TMainExportAllVO vo : list) {
//									temp = mapContract.get(vo.getMainId());
//									if (temp != null) {
//										vo.setField26(temp.getField26());
//										vo.setField27(temp.getField27());
//										vo.setField28(temp.getField28());
//										vo.setField29(temp.getField29());
//										vo.setField30(temp.getField30());
//									}
									temp = mapEducation.get(vo.getMainId());
									if (temp != null) {
										vo.setField36(temp.getField36());
										vo.setField37(temp.getField37());
										vo.setField38(temp.getField38());
										vo.setField41(temp.getField41());
										vo.setField42(temp.getField42());
									}
									temp = mapBad.get(vo.getMainId());
									if (temp != null) {
										vo.setField63(temp.getField63());
									}
									temp = mapDisability.get(vo.getMainId());
									if (temp != null) {
										vo.setField54(temp.getField54());
										vo.setField55(temp.getField55());
										vo.setField56(temp.getField56());
										vo.setField57(temp.getField57());
										vo.setField58(temp.getField58());
										vo.setField59(temp.getField59());
										vo.setField60(temp.getField60());
										vo.setField61(temp.getField61());
										vo.setField62(temp.getField62());
									}
									temp = mapWork.get(vo.getMainId());
									if (temp != null) {
										vo.setField44(temp.getField44());
										vo.setField45(temp.getField45());
										vo.setField46(temp.getField46());
										vo.setField47(temp.getField47());
									}
									temp = mapFamily.get(vo.getMainId());
									if (temp != null) {
										vo.setField48(temp.getField48());
										vo.setField49(temp.getField49());
										vo.setField50(temp.getField50());
									}
									temp = mapProfessional.get(vo.getMainId());
									if (temp != null) {
										vo.setField52(temp.getField52());
										vo.setField53(temp.getField53());
									}
								}
								writeSheet = EasyExcelFactory.writerSheet(name + index);
								excelWriter.write(list, writeSheet.build());
								index++;
							}
							if (Common.isNotNull(list)) {
								list.clear();
							}
						}
						// 1工作经历
						index = 1;
						count = baseMapper.getTEmpMainAllCountOneWork(searchVo);
						for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
							// 获取实际记录
							searchVo.setLimitStart(i);
							searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
							list = baseMapper.getTEmpMainAllListOneWork(searchVo);
							if (Common.isNotNull(list)) {
								writeSheet = EasyExcelFactory.writerSheet("工作经历" + index);
								excelWriter.write(list, writeSheet.build());
								index++;
							}
							if (Common.isNotNull(list)) {
								list.clear();
							}
						}
						// 2家庭成员
						index = 1;
						count = baseMapper.getTEmpMainAllCountTwoFamily(searchVo);
						for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
							// 获取实际记录
							searchVo.setLimitStart(i);
							searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
							list = baseMapper.getTEmpMainAllListTwoFamily(searchVo);
							if (Common.isNotNull(list)) {
								writeSheet = EasyExcelFactory.writerSheet("家庭成员" + index);
								excelWriter.write(list, writeSheet.build());
								index++;
							}
							if (Common.isNotNull(list)) {
								list.clear();
							}
						}
						// 3职业资格
						index = 1;
						count = baseMapper.getTEmpMainAllCountThreeProfessional(searchVo);
						for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
							// 获取实际记录
							searchVo.setLimitStart(i);
							searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
							list = baseMapper.getTEmpMainAllListThreeProfessional(searchVo);
							if (Common.isNotNull(list)) {
								writeSheet = EasyExcelFactory.writerSheet("职业资格" + index);
								excelWriter.write(list, writeSheet.build());
								index++;
							}
							if (Common.isNotNull(list)) {
								list.clear();
							}
						}
					} else {
						WriteSheet writeSheet = EasyExcelFactory.writerSheet(name + index).build();
						excelWriter.write(list, writeSheet);
					}
					if (Common.isNotNull(list)) {
						list.clear();
					}
				}
				out.flush();
				if (excelWriter != null) {
					excelWriter.finish();
				}
			} catch (Exception e) {
				log.error("执行异常", e);
			} finally {
				try {
					// 结束后将状态更新为已导出
					exportLimit.setDeleteFlag(CommonConstants.ONE_INT);
					exportLimit.setUpdateBy(user.getNickname());
					exportLimit.setUpdateTime(LocalDateTime.now());
					tArchivesExportLimitMapper.updateById(exportLimit);
					if (null != out) {
						out.close();
					}
				} catch (IOException e) {
					log.error("执行异常", e);
				}
			}
		}
	}

	private Map<String,String> getConverterDicTypeAndArea(Class<?> clazz) {
		// 得到所有定义字段
		Field[] allFields = clazz.getDeclaredFields();
		Map<String,String> nameDicMap = new HashMap<>();
		List<Field> fields = new ArrayList<>();
		// 将需要字典表头存起来备用，如果没传，则全部翻译
		for (Field field : allFields) {
			if (field.isAnnotationPresent(ExcelAttribute.class)) {
				fields.add(field);
			}
		}
		ExcelAttribute attr;
		Field field;
		for (int j = 0; j < fields.size(); j++) {
			field = fields.get(j);
			attr = field.getAnnotation(ExcelAttribute.class);
			if (Common.isNotNull(field) && Common.isNotNull(attr)){
				if (Common.isNotNull(attr.dataType())) {
					nameDicMap.put(field.getName(), attr.dataType());
				} else if (Common.isNotNull(attr.isArea()) && attr.isArea()) {
					nameDicMap.put(field.getName(), CacheConstants.AREA_VALUE_ALL);
				}
			}
		}
		return nameDicMap;
	}

	/**
	 * @Description: 详情
	 * @Author: huyc
	 * @Date: 2024/6/28 11:19
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<com.yifu.cloud.plus.v1.yifu.archives.vo.EmpMainDetailVo>
	 **/
	@Override
	public R<EmpMainDetailVo> getInfoById(String id,String deptId) {
		EmpMainDetailVo vo = new EmpMainDetailVo();
		if (id != null) {
			// 员工不良记录表
			TEmpBadRecord tEmpBadRecord = tEmpBadRecordService.getByEmpId(id);
			vo.setTEmpBadRecord(tEmpBadRecord);
			// 紧急联络人
			TEmpContactInfo tEmpContactInfo = tEmpContactInfoService.getByEmpId(id);
			vo.setTEmpContactInfo(tEmpContactInfo);
			// 员工伤残信息表
			TEmpDisabilityInfo tEmpDisabilityInfo = tEmpDisabilityInfoService.getByEmpId(id);
			vo.setTEmpDisabilityInfo(tEmpDisabilityInfo);
			// 员工学历信息表
			TEmpEducation tEmpEducation = tEmpEducationService.getByEmpId(id);
			if (tEmpEducation != null) {
				List<TAttaInfo> attaInfoList = tAttaInfoService.getTAttaInfoListByDoMainId(tEmpEducation.getId());
				if (attaInfoList != null) {
					URL url;
					for (TAttaInfo atta : attaInfoList) {
						url = ossUtil.getObjectUrl(null, atta.getAttaSrc());
						atta.setAttaUrl(String.valueOf(url));
					}
				}
				tEmpEducation.setAttaList(attaInfoList);
			}
			vo.setTEmpEducation(tEmpEducation);
			// 员工家庭信息表
			List<TEmpFamily> tEmpFamily = tEmpFamilyService.getListByEmpId(id);
			vo.setTEmpFamilyList(tEmpFamily);
			// 人员档案表
			TEmployeeInfo tEmployeeInfo = tEmployeeInfoMapper.selectById(id);
			vo.setTEmployeeInfo(tEmployeeInfo);
			// 项目档案表
			TEmployeeProject tEmployeeProject = tEmployeeProjectService.getByEmpIdAndDeptId(id,deptId);
			vo.setTEmployeeProject(tEmployeeProject);
			// 员工职业资格信息表
			List<TEmpProfessionalQualification> tEmpProfessionalQualificationList = tEmpProfessionalQualificationService.getListByEmpId(id);

			if (tEmpProfessionalQualificationList != null) {
				List<TAttaInfo> attaInfoList;
				for (TEmpProfessionalQualification info : tEmpProfessionalQualificationList) {
					attaInfoList = tAttaInfoService.getTAttaInfoListByDoMainId(info.getId());
					if (attaInfoList != null) {
						URL url;
						for (TAttaInfo atta : attaInfoList) {
							url = ossUtil.getObjectUrl(null, atta.getAttaSrc());
							atta.setAttaUrl(String.valueOf(url));
						}
						info.setAttaList(attaInfoList);
					}
				}
			}

			vo.setTEmpProfessionalQualificationList(tEmpProfessionalQualificationList);
			// 员工工作履历信息表
			List<TEmpWorkRecording> tEmpWorkRecording = tEmpWorkRecordingService.getListByEmpId(id);
			vo.setTEmpWorkRecordingList(tEmpWorkRecording);

			// 附件 9身份证 10 户口本；21（预入职申明签名）；22（预入职确认签名）；23（预入职pdf文件)
			List<TAttaInfo> attaInfoList = tAttaInfoService.getTAttaInfoListByDoMainId(id);
			if (attaInfoList != null) {
				URL url;
				for (TAttaInfo atta : attaInfoList) {
					url = ossUtil.getObjectUrl(null, atta.getAttaSrc());
					atta.setAttaUrl(String.valueOf(url));
				}
			}
			vo.setAttaInfoList(attaInfoList);
			return R.ok(vo);
		} else {
			return R.failed("根据ID，未找到人员档案主表！");
		}
	}

	/**
	 * @Description: 转化
	 * @Author: hgw
	 * @Date: 2024/6/26 11:19
	 **/
	private List<String> getNewArrayList(String[] strArr) {
		return Arrays.asList(strArr);
	}


	/**
	 * @Description: 获取前端客服的所有项目权限
	 * @Author: huych
	 * @Date: 2025/3/13 17:02
	 * @return:
	 **/
	public void initSearchVo(EmployeeRegistrationPreSearchVo searchVo) {
		YifuUser user = SecurityUtils.getUser();
		long roleId = 1839501715787390978L;
		boolean isSsc = this.haveRole(user, roleId);
		if (isSsc || CommonConstants.ZERO_STRING.equals(user.getSystemFlag())) {
			searchVo.setAuthSql(null);
			return;
		}
		if (Common.isNotNull(searchVo.getType()) && CommonConstants.ONE_STRING.equals(searchVo.getType())) {
			searchVo.setAuthSql(null);
			//获取项目信息
			List<String> deptNos = tSettleDomainService.getAllDeptByCustomerLoginName(user.getUsername());
			if (null != deptNos && !deptNos.isEmpty()) {
				searchVo.setDeptNoList(deptNos);
			} else {
				searchVo.setId(CommonConstants.ONE_STRING_NEGATE);
			}
		}
	}
	public boolean haveRole(YifuUser user, long roleId) {
		List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
		for (Long role : roleList) {
			if (role == roleId) {
				return true;
			}
		}
		return false;
	}
}
