/*
 *    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.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.plugin.excel.vo.ErrorMessage;
import com.yifu.cloud.plus.v1.yifu.archives.constants.ArchivesConstants;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
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.TEmployeeInfoService;
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.EmployeeProjectVO;
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.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.MsgUtils;
import com.yifu.cloud.plus.v1.yifu.common.core.util.NoUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;

import java.util.*;
import java.util.stream.Collectors;

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

	private TEmployeeInfoService tEmployeeInfoService;

	private TEmployeeLogService tEmployeeLogService;

	private TEmployeeInfoMapper tEmployeeInfoMapper;

	private TEmployeeProjectMapper tEmployeeProjectMapper;

	private TSettleDomainService tSettleDomainService;

	@Override
	public R addCheck(TEmployeeProject tEmployeeProject) {

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

		//身份证系统中是否已有
		TEmployeeInfo tEmployeeInfo = tEmployeeInfoService.getOne(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 (!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.STATUS_NORMAL.equals(tEmployeeInfo.getFileStatus())) {
						return R.ok(map, "该人员已减项，是否“复项”");
					} else {
						map.put("employeeId", tEmployeeInfo.getId());
						return R.ok(map, "该人员已减档减项，是否“复档复项”");
					}
				}
			}
			//状态为草稿、已审核
			if (CommonConstants.dingleDigitIntArray[0] == employeeProject.getStatus() ||
					CommonConstants.dingleDigitIntArray[1] == employeeProject.getStatus()) {
				return R.failed("人员已有该项目信息，禁止重复添加！");
			}
		} else {
			if (Common.isEmpty(tEmployeeInfo)) {
				return R.failed("该人员暂无档案信息，禁止关联项目，如要添加，请先至“在档人员”处建档");
			}
			//判断是否已经减档
			if (CommonConstants.ONE_STRING.equals(tEmployeeInfo.getFileStatus())) {
				map.put("employeeId", tEmployeeInfo.getId());
				return R.ok(null,"该人员在离职库已存在，是否“恢复档案”");
			}
		}
		return R.ok();
	}

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

	@Override
	public R deleteEmpPro(TEmployeeProject tEmployeeProject) {
		if (Common.isNotNull(tEmployeeProject)) {
			TEmployeeInfo tEmployeeInfo = tEmployeeInfoService.getById(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]);
				tEmployeeInfoService.updateById(tEmployeeInfo);
			}
			tEmployeeProject.setProjectStatus(CommonConstants.dingleDigitIntArray[1]);
			this.updateById(tEmployeeProject);
			addEmpLog(CommonConstants.dingleDigitIntArray[2],tEmployeeInfo.getId(),tEmployeeProject.getId(),ArchivesConstants.REDUCE_EMP_PROJECT_CONTENT);
			return R.ok();
		}
		return R.failed("传参为空！");
	}

	/**
	 * 新增档案操作记录
	 * @param type
	 * @param empId
	 * @param empProId
	 * @param content
	 * @author huyc
	 * @date 2022-06-20 17:19:40
	 */
	public void addEmpLog(int type, String empId, String empProId, String content) {
		TEmployeeLog tEmployeeLog = new TEmployeeLog();
		tEmployeeLog.setEmpId(empId);
		tEmployeeLog.setType(type);
		tEmployeeLog.setProjectId(empProId);
		tEmployeeLog.setContent(content);
		tEmployeeLogService.save(tEmployeeLog);
	}

	/**
	 * 新增档案操作记录
	 * @param excelVOList
	 * @param bindingResult
	 * @param
	 * @author huyc
	 * @date 2022-06-20 18:52:16
	 */
	@Override
	public R<List<ErrorMessage>> importListAdd(List<EmployeeProjectVO> excelVOList, BindingResult bindingResult, String idAdd) {
		// 通用校验获取失败的数据
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
		Map<Long,ErrorMessage> errorMsgMap = new HashMap<>();
		if (Common.isNotNull(errorMessageList)){
			errorMessageList.stream().forEach(errorMessage -> errorMsgMap.put(errorMessage.getLineNum(),errorMessage));
		}

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

			// 已有验证报错直接下一个
			if (Common.isNotNull(errorMsgMap.get(i+2))){
				continue;
			}

			//根据身份证获取人员档案
			TEmployeeInfo tEmployeeInfo = tEmployeeInfoService.getOne(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)) {
				insertExcelPost(excel, insertList);
				insertExcelPro(excel, proInsList);
				//档案有（在档人员），项目无
			} else if (Common.isNotNull(tEmployeeInfo) && Common.isEmpty(tEmployeeProject)
					&& CommonConstants.dingleDigitIntArray[0] == tEmployeeInfo.getFileStatus()) {
				updateExcelPost(excel, updateList, tEmployeeInfo);
				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);
				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);
					updateExcelPro(excel, proupdateList, tEmployeeProject);
					//档案有（离职库），项目无；
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
					&& Common.isEmpty(tEmployeeProject) ) {
					updateExcelPost(excel, updateList, tEmployeeInfo);
					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);
					updateExcelPro(excel, proupdateList, tEmployeeProject);
				}
				//不允许复档复项
			} else {
				//档案有（离职库），项目（已减档）
				if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
						&& Common.isNotNull(tEmployeeProject) && CommonConstants.dingleDigitIntArray[1] == tEmployeeProject.getProjectStatus()) {
					errorMsg.add(MsgUtils.getMessage(ErrorCodes.CHECKS_EMP_PROJECT_ERROR));
				} else if (Common.isNotNull(tEmployeeInfo) && CommonConstants.dingleDigitIntArray[1] == tEmployeeInfo.getFileStatus()
						&& Common.isEmpty(tEmployeeProject)) {
					errorMsg.add(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()){
					errorMsg.add(MsgUtils.getMessage(ErrorCodes.CHECKS_REDUCE_PROJECT_ERROR));
				}
			}

			if (!CollUtil.isEmpty(errorMsg)) {
				errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg));
			}
		}

		try {
			if (insertList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeInfoMapper.insertExcelEmployeeInfo(insertList);
			}
			if (updateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeInfoMapper.updateExcelEmployeeInfo(updateList);
			}
			if (proInsList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeProjectMapper.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));
				tEmployeeProjectMapper.updateEmpIdById(updList);
			}
			if (proupdateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeProjectMapper.updateExcelEmpProject(proupdateList);
			}
		} catch (Exception e) {
			log.error("数据更新异常",e);
		}
		if (CollUtil.isNotEmpty(errorMessageList)) {
			return R.failed(errorMessageList);
		}
		return R.ok();
	}


	/**
	 * @Author huyc
	 * @Description  批量更新项目档案信息
	 * @Date 19:25 2022/6/21
	 **/
	@Override
	public R<List<ErrorMessage>> importEmpProjectUpdate(List<EmployeeProjectVO> excelVOList, BindingResult bindingResult) {
		// 通用校验获取失败的数据
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
		Map<Long,ErrorMessage> errorMsgMap = new HashMap<>();
		if (Common.isNotNull(errorMessageList)){
			errorMessageList.stream().forEach(errorMessage -> errorMsgMap.put(errorMessage.getLineNum(),errorMessage));
		}

		List<TEmployeeProject> updateList = new ArrayList<>();
		// 个性化校验逻辑
		List<TEmployeeProject> list = this.list();

		Set<String> errorMsg;
		// 执行数据插入操作 组装
		for (int i = 0; i < excelVOList.size(); i++) {
			// 已有验证报错直接下一个
			if (Common.isNotNull(errorMsgMap.get(i + 2))) {
				continue;
			}
			errorMsg = new HashSet<>();
			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));
			if (Common.isEmpty(tEmployeeProject)) {
				errorMsg.add(MsgUtils.getMessage(ErrorCodes.CHECKS_EMP_EXIT_ERROR, excel.getEmpName()));
			}

			// 数据合法情况
			if (CollUtil.isEmpty(errorMsg)) {
				updateExcelPro(excel,updateList,tEmployeeProject);
			} else {
				// 数据不合法
				errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg));
			}
		}
		try {
			if (updateList.size() > CommonConstants.dingleDigitIntArray[0]) {
				tEmployeeProjectMapper.updateExcelEmpProject(updateList);
			}

		} catch (Exception e) {
			log.error("数据更新异常",e);
		}
		if (CollUtil.isNotEmpty(errorMessageList)) {
			return R.failed(errorMessageList);
		}
		return R.ok();
	}

	/**
	 * 插入excel Post
	 */
	private void insertExcelPost(EmployeeProjectVO excel,List<TEmployeeInfo> insertList) {
		TEmployeeInfo insTEmployeeInfo = new TEmployeeInfo();
		BeanUtil.copyProperties(excel, insTEmployeeInfo);
		insTEmployeeInfo.setFileStatus(CommonConstants.dingleDigitIntArray[0]);
		insTEmployeeInfo.setDeleteFlag(CommonConstants.STATUS_NORMAL);
		insTEmployeeInfo.setStatus(CommonConstants.dingleDigitIntArray[0]);
		//TODO HUYC 员工编码生成规则
		insTEmployeeInfo.setEmpCode("");
		YifuUser user = SecurityUtils.getUser();
		insTEmployeeInfo.setCreateBy(user.getId());
		insTEmployeeInfo.setCreateName(user.getNickname());
		insertList.add(insTEmployeeInfo);
	}

	/**
	 * 插入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 str = "";
		String EmpNo = tEmployeeProjectMapper.findEmployeeMaxOnlyNoByDepId(insTEmployeePro.getDeptNo());
		if (!Common.isEmpty(EmpNo)) {
			str = NoUtil.productionNo(EmpNo, CommonConstants.EMPLOYEE_INIT_NO_START);
		} else {
			str = insTEmployeePro.getDeptNo() + CommonConstants.EMPLOYEE_INIT_NO;
		}
		insTEmployeePro.setEmpNo(str);
		//TODO HUYC 员工编码生成规则
		insTEmployeePro.setEmpCode("");
		YifuUser user = SecurityUtils.getUser();
		insTEmployeePro.setCreateBy(user.getId());
		insTEmployeePro.setCreateName(user.getNickname());
		proInsList.add(insTEmployeePro);
	}

	/**
	 * 更新人员档案
	 */
	private void updateExcelPost(EmployeeProjectVO excel,List<TEmployeeInfo> updateList,TEmployeeInfo tEmployeeInfo) {
		BeanUtil.copyProperties(excel, tEmployeeInfo);
		YifuUser user = SecurityUtils.getUser();
		tEmployeeInfo.setUpdateBy(user.getId());
		updateList.add(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);
	}

	@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));
	}
}
