/*
 *    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.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.EmployeeRegistrationPre;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeePreLog;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TEmployeePreLogDetail;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TEmployeePreLogMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.TEmployeePreLogDetailService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TEmployeePreLogService;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TEmployeePreLogSearchVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.equator.HrEquator;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprInsurancesProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.HttpDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TEmployeeInsurancePre;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

import static com.alibaba.fastjson.serializer.SerializerFeature.*;

/**
 * 入职确认信息变更日志表
 *
 * @author hgw
 * @date 2025-04-07 15:35:05
 */
@Log4j2
@Service
@AllArgsConstructor
@EnableConfigurationProperties(DaprInsurancesProperties.class)
public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMapper, TEmployeePreLog> implements TEmployeePreLogService {
	private final DaprInsurancesProperties daprInsurancesProperties;
	private final TEmployeePreLogDetailService tEmployeePreLogDetailService;

	/**
	 * 入职确认信息变更日志表简单分页查询
	 *
	 * @param tEmployeePreLog 入职确认信息变更日志表
	 * @return
	 */
	@Override
	public IPage<TEmployeePreLog> getTEmployeePreLogPage(Page<TEmployeePreLog> page, TEmployeePreLogSearchVo tEmployeePreLog) {
		if (Common.isNotNull(tEmployeePreLog.getPreId())) {
			IPage<TEmployeePreLog> pageList = baseMapper.getTEmployeePreLogPage(page, tEmployeePreLog);
			List<TEmployeePreLogDetail> detailList = tEmployeePreLogDetailService.getTEmployeePreLogDetailList(tEmployeePreLog.getPreId());
			Map<String, List<TEmployeePreLogDetail>> detailMap = new HashMap<>();
			if (detailList != null && !detailList.isEmpty()) {
				List<TEmployeePreLogDetail> detailList1;
				for (TEmployeePreLogDetail detail : detailList) {
					detailList1 = detailMap.get(detail.getPreLogId());
					if (detailList1 == null) {
						detailList1 = new ArrayList<>();
					}
					detailList1.add(detail);
					detailMap.put(detail.getPreLogId(), detailList1);
				}
			}
			for (TEmployeePreLog tEmployeePreLog1 : pageList.getRecords()) {
				if (detailMap.get(tEmployeePreLog1.getId()) != null) {
					tEmployeePreLog1.setDetailList(detailMap.get(tEmployeePreLog1.getId()));
				}
			}
			return pageList;
		}
		return null;
	}


	@Override
	public List<TEmployeePreLog> noPageDiy(TEmployeePreLogSearchVo searchVo) {
		LambdaQueryWrapper<TEmployeePreLog> wrapper = buildQueryWrapper(searchVo);
		List<String> idList = Common.getList(searchVo.getIds());
		if (Common.isNotNull(idList)) {
			wrapper.in(TEmployeePreLog::getId, idList);
		}
		if (searchVo.getLimitStart() >= 0 && searchVo.getLimitEnd() > 0) {
			wrapper.last(" limit " + searchVo.getLimitStart() + "," + searchVo.getLimitEnd());
		}
		wrapper.orderByDesc(BaseEntity::getCreateTime);
		return baseMapper.selectList(wrapper);
	}


	private LambdaQueryWrapper<TEmployeePreLog> buildQueryWrapper(TEmployeePreLogSearchVo entity) {
		LambdaQueryWrapper<TEmployeePreLog> wrapper = Wrappers.lambdaQuery();
		if (ArrayUtil.isNotEmpty(entity.getCreateTimes())) {
			wrapper.ge(TEmployeePreLog::getCreateTime, entity.getCreateTimes()[0])
					.le(TEmployeePreLog::getCreateTime,
							entity.getCreateTimes()[1]);
		}
		if (Common.isNotNull(entity.getCreateName())) {
			wrapper.eq(TEmployeePreLog::getCreateName, entity.getCreateName());
		}
		return wrapper;
	}

	private static final SerializerFeature[] features = new SerializerFeature[]{
			WriteMapNullValue, WriteNullNumberAsZero, WriteNullListAsEmpty,
			WriteNullStringAsEmpty, WriteDateUseDateFormat
	};

	// 修改入职确认信息，忽略的字段变更日志。
	// 2025-4-15 15:44:34 倩倩与龙弟确认：processStatus 不做忽略，如果点确认重置了状态，要有日志，只是目前日志没体现状态。
	private static final List<String> IGNORE_FIELD = new ArrayList<>();
	static {
		IGNORE_FIELD.add("joinLeaveDate");
		IGNORE_FIELD.add("createTime");
		IGNORE_FIELD.add("modelType");

		IGNORE_FIELD.add("empPhone");
		IGNORE_FIELD.add("employeeName");
		IGNORE_FIELD.add("empIdcard");
		IGNORE_FIELD.add("deptNo");
		IGNORE_FIELD.add("deptName");
		IGNORE_FIELD.add("deptId");
		IGNORE_FIELD.add("customerUsername");
		IGNORE_FIELD.add("customerUserLoginname");
		IGNORE_FIELD.add("dataSource");
		IGNORE_FIELD.add("position");
		IGNORE_FIELD.add("createBy");
		IGNORE_FIELD.add("createName");
		IGNORE_FIELD.add("updateBy");
		IGNORE_FIELD.add("isAddress");
	}

	private static final List<String> PRE_IGNORE_FIELD = new ArrayList<>();
	static {
		IGNORE_FIELD.add("createTime");
		IGNORE_FIELD.add("deptId");
		IGNORE_FIELD.add("dataSource");
		IGNORE_FIELD.add("createBy");
		IGNORE_FIELD.add("createName");
		IGNORE_FIELD.add("updateBy");
	}

	@Override
	public void saveModifyAndUpdateInsurance(String empPreId, EmployeeRegistrationPre oldInfo
			, EmployeeRegistrationPre newInfo, YifuUser user, Map<String, TEmployeeInsurancePre> oldMap) {
		try {
			//比较记录不影响业务逻辑，用try套住
			//比较差异
			String differenceKey = HrEquator.comparisonValue(oldInfo, newInfo);
			//如果有差异保存差异
			List<TEmployeeInsurancePre> newList = newInfo.getInsurancePreList();

			String diffTitle = null;
			String logId = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
			// 要保存的明细
			List<TEmployeePreLogDetail> detailList = new ArrayList<>();
			// 档案信息修改
			TEmployeePreLogDetail detailEmpLog = null;
			if (Common.isNotNull(differenceKey) && !"insurancePreList".equals(differenceKey)) {
				differenceKey = differenceKey.replace("insurancePreList","");
				diffTitle = "档案信息";
				detailEmpLog = new TEmployeePreLogDetail();
				detailEmpLog.setModelType(CommonConstants.TWO_STRING);
				detailEmpLog.setType(CommonConstants.ONE_STRING);
				this.setLogBaseInfo(empPreId, oldInfo, newInfo, user, differenceKey, logId, detailEmpLog);
				detailList.add(detailEmpLog);
			}
			// 有ID，修改或删除
			if (oldMap == null) {
				oldMap = new HashMap<>();
			}
			List<TEmployeeInsurancePre> saveOrUpdateList = new ArrayList<>();
			if (newList != null && !newList.isEmpty()) {
				// 是否修改了商险
				boolean isModifyInsurance = false;
				TEmployeeInsurancePre oldInsurance;
				String differenceInsuranceKey;
				TEmployeePreLogDetail detailInsuranceLog;
				for (TEmployeeInsurancePre newInsurance : newList) {
					differenceInsuranceKey = null;
					if (Common.isNotNull(newInsurance.getModelType())) {
						// 1：新增
						if (CommonConstants.ONE_STRING.equals(newInsurance.getModelType())) {

							saveOrUpdateList.add(newInsurance);
							detailInsuranceLog = new TEmployeePreLogDetail();
							detailInsuranceLog.setModelType(newInsurance.getModelType());
							detailInsuranceLog.setType(CommonConstants.TWO_STRING);
							this.setLogBaseInfo(empPreId, null, newInsurance, user, differenceInsuranceKey, logId, detailInsuranceLog);
							isModifyInsurance = true;
							detailList.add(detailInsuranceLog);
						} else if (CommonConstants.TWO_STRING.equals(newInsurance.getModelType())) {

							// 2：修改有老ID
							if (Common.isNotNull(newInsurance.getId())) {
								oldInsurance = oldMap.get(newInsurance.getId());
								if (oldInsurance != null) {
									differenceInsuranceKey = HrEquator.comparisonValueIgnoreField(oldInsurance, newInsurance, IGNORE_FIELD);
								}
								if (Common.isNotNull(differenceInsuranceKey) || oldInsurance == null) {
									detailInsuranceLog = new TEmployeePreLogDetail();
									detailInsuranceLog.setModelType(CommonConstants.TWO_STRING);
									detailInsuranceLog.setType(CommonConstants.TWO_STRING);
									this.setLogBaseInfo(empPreId, oldInsurance, newInsurance, user, differenceInsuranceKey, logId, detailInsuranceLog);
									isModifyInsurance = true;
									detailList.add(detailInsuranceLog);
								}
							} else {
								// 2：修改无老ID
								detailInsuranceLog = new TEmployeePreLogDetail();
								detailInsuranceLog.setModelType(CommonConstants.ONE_STRING);
								detailInsuranceLog.setType(CommonConstants.TWO_STRING);
								this.setLogBaseInfo(empPreId, null, newInsurance, user, differenceInsuranceKey, logId, detailInsuranceLog);
								isModifyInsurance = true;
								detailList.add(detailInsuranceLog);
							}
							saveOrUpdateList.add(newInsurance);
						} else if (CommonConstants.THREE_STRING.equals(newInsurance.getModelType())) {
							// 3：删除
							detailInsuranceLog = new TEmployeePreLogDetail();
							detailInsuranceLog.setModelType(newInsurance.getModelType());
							detailInsuranceLog.setType(CommonConstants.TWO_STRING);
							this.setLogBaseInfo(empPreId, newInsurance, null, user, differenceInsuranceKey, logId, detailInsuranceLog);
							isModifyInsurance = true;
							detailList.add(detailInsuranceLog);
						}
					} else {
						// 没有调整的
						isModifyInsurance = true;
						saveOrUpdateList.add(newInsurance);
					}
				}
				// 如果变更了
				if (isModifyInsurance) {
					if (Common.isNotNull(diffTitle)) {
						diffTitle += "、商险信息";
					} else {
						diffTitle = "商险信息";
					}
				}
			}
			// 有修改，则加日志
			if (Common.isNotNull(diffTitle)) {
				TEmployeePreLog empPreLog = new TEmployeePreLog();
				empPreLog.setId(logId);
				empPreLog.setPreId(empPreId);
				empPreLog.setDiffTitle(diffTitle);
				empPreLog.setCreateTime(LocalDateTime.now());
				if (Common.isNotNull(user)) {
					empPreLog.setCreateBy(user.getId());
					empPreLog.setCreateName(user.getNickname());
				}
				baseMapper.insert(empPreLog);
				if (!detailList.isEmpty()) {
					tEmployeePreLogDetailService.saveBatch(detailList);
				}
			}
			if (!saveOrUpdateList.isEmpty()) {
				HttpDaprUtil.invokeMethodPost(daprInsurancesProperties.getAppUrl(), daprInsurancesProperties.getAppId()
						, "/temployeeinsurancepre/inner/saveOrUpdateInsuranceList"
						, saveOrUpdateList, Boolean.class, SecurityConstants.FROM_IN);
			} else {
				HttpDaprUtil.invokeMethodPost(daprInsurancesProperties.getAppUrl(), daprInsurancesProperties.getAppId()
						, "/temployeeinsurancepre/inner/deleteInsuranceByPreId"
						, empPreId, Boolean.class, SecurityConstants.FROM_IN);
			}
		} catch (Exception e) {
			log.error(JSON.toJSON(newInfo) + "插入修改记录报错>>>", e);
		}
	}

	@Override
	public void saveUpdateInsurance(String empPreId, EmployeeRegistrationPre oldInfo
			, EmployeeRegistrationPre newInfo, String userId, String nickName, Map<String, TEmployeeInsurancePre> oldMap) {
		try {
			//比较记录不影响业务逻辑，用try套住
			//比较差异
			String differenceKey = HrEquator.comparisonValue(oldInfo, newInfo);
			//如果有差异保存差异
			List<TEmployeeInsurancePre> newList = newInfo.getInsurancePreList();
			String diffTitle = null;
			String logId = String.valueOf(UUID.randomUUID()).replaceAll("-", "");
			// 要保存的明细
			List<TEmployeePreLogDetail> detailList = new ArrayList<>();
			// 档案信息修改
			TEmployeePreLogDetail detailEmpLog = null;
			if (Common.isNotNull(differenceKey) && !"insurancePreList".equals(differenceKey)) {
				differenceKey = differenceKey.replace("insurancePreList","");
				diffTitle = "档案信息二次确认";
				detailEmpLog = new TEmployeePreLogDetail();
				detailEmpLog.setModelType(CommonConstants.TWO_STRING);
				detailEmpLog.setType(CommonConstants.ONE_STRING);
				this.setPreLogBaseInfo(empPreId, oldInfo, newInfo, userId, nickName, differenceKey, logId, detailEmpLog);
				detailList.add(detailEmpLog);
			}
			if (newList != null && !newList.isEmpty()) {
				// 是否修改了商险
				boolean isModifyInsurance = false;
				TEmployeeInsurancePre oldInsurance;
				String differenceInsuranceKey;
				TEmployeePreLogDetail detailInsuranceLog;
				for (TEmployeeInsurancePre newInsurance : newList) {
					differenceInsuranceKey = null;
					// 2：修改有老ID
					if (Common.isNotNull(newInsurance.getId())) {
						oldInsurance = oldMap.get(newInsurance.getId());
						if (oldInsurance != null) {
							differenceInsuranceKey = HrEquator.comparisonValueIgnoreField(oldInsurance, newInsurance,PRE_IGNORE_FIELD);
						}
						if (Common.isNotNull(differenceInsuranceKey) || oldInsurance == null) {
							detailInsuranceLog = new TEmployeePreLogDetail();
							detailInsuranceLog.setModelType(CommonConstants.TWO_STRING);
							detailInsuranceLog.setType(CommonConstants.TWO_STRING);
							this.setPreLogBaseInfo(empPreId, oldInsurance, newInsurance, userId, nickName, differenceInsuranceKey, logId, detailInsuranceLog);
							isModifyInsurance = true;
							detailList.add(detailInsuranceLog);
						}
					}
				}
				// 如果变更了
				if (isModifyInsurance) {
					if (Common.isNotNull(diffTitle)) {
						diffTitle += "、商险信息";
					} else {
						diffTitle = "商险信息";
					}
				}
			}
			// 有修改，则加日志
			if (Common.isNotNull(diffTitle)) {
				TEmployeePreLog empPreLog = new TEmployeePreLog();
				empPreLog.setId(logId);
				empPreLog.setPreId(empPreId);
				empPreLog.setDiffTitle(diffTitle);
				empPreLog.setCreateTime(LocalDateTime.now());
				if (Common.isNotNull(userId) && Common.isNotNull(nickName)) {
					empPreLog.setCreateBy(userId);
					empPreLog.setCreateName(nickName);
				}
				baseMapper.insert(empPreLog);
				if (!detailList.isEmpty()) {
					tEmployeePreLogDetailService.saveBatch(detailList);
				}
			}
		} catch (Exception e) {
			log.error(JSON.toJSON(newInfo) + "插入修改记录报错>>>", e);
		}
	}

	/**
	 * @Description: 填充基本信息
	 * @Author: hgw
	 * @Date: 2025/4/8 10:49
	 * @return: void
	 **/
	private void setLogBaseInfo(String empPreId, Object oldInfo, Object newInfo
			, YifuUser user, String differenceKey, String logId, TEmployeePreLogDetail detailEmpLog) {
		detailEmpLog.setPreId(empPreId);
		detailEmpLog.setPreLogId(logId);
		detailEmpLog.setDifferenceInfo(differenceKey);
		detailEmpLog.setCreateTime(LocalDateTime.now());
		if (Common.isNotNull(user)) {
			detailEmpLog.setCreateBy(user.getId());
			detailEmpLog.setCreateName(user.getNickname());
		}
		if (Common.isNotNull(oldInfo)) {
			detailEmpLog.setOldInfo(JSON.toJSONString(oldInfo, features));
		}
		if (Common.isNotNull(newInfo)) {
			detailEmpLog.setNewInfo(JSON.toJSONString(newInfo, features));
		}
	}

	/**
	 * @Description: 填充基本信息
	 * @Author: huyc
	 * @Date: 2025/4/11 10:49
	 * @return: void
	 **/
	private void setPreLogBaseInfo(String empPreId, Object oldInfo, Object newInfo
			, String userId, String nickName, String differenceKey, String logId, TEmployeePreLogDetail detailEmpLog) {
		detailEmpLog.setPreId(empPreId);
		detailEmpLog.setPreLogId(logId);
		detailEmpLog.setDifferenceInfo(differenceKey);
		detailEmpLog.setCreateTime(LocalDateTime.now());
		detailEmpLog.setCreateBy(userId);
		detailEmpLog.setCreateName(nickName);
		if (Common.isNotNull(oldInfo)) {
			detailEmpLog.setOldInfo(JSON.toJSONString(oldInfo, features));
		}
		if (Common.isNotNull(newInfo)) {
			detailEmpLog.setNewInfo(JSON.toJSONString(newInfo, features));
		}
	}

}
