/*
 *    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 com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yifu.cloud.plus.v1.yifu.archives.config.GzConfig;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TGzEmpInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TGzOfferInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.*;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 瓜子系统交互任务处理异步任务类
 *
 * @author chenyuxi
 * @date 2025-07-11
 * @since 1.7.13
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TGzPushHandleServiceImpl implements TGzPushHandleService {

	private final TGzPushEntryService tGzPushEntryService;

	private final TGzEmpInfoMapper tGzEmpInfoMapper;

	private final TGzOfferInfoMapper tGzOfferInfoMapper;

	private final TGzEmpInfoService tGzEmpInfoService;

	private final TAttaInfoService tAttaInfoService;

	@Autowired
	private GzConfig gzConfig;

	@Autowired
	private OSSUtil ossUtil;

	private RestTemplate restTemplate = new RestTemplate();

	// 任务类型是改状态的: 4：待接受Offer，5：拒绝Offer，6：接受offer，9：候选人填写信息，10：取消offer，12：候选人信息审核，13：待签署
	private final String[] taskTypeArr = {"4", "5", "6", "9", "10", "12", "13"};


	/**
	 * 处理异步的推送任务
	 *
	 * @param tGzPushEntry 瓜子系统交互任务跟进表
	 */
	@Override
	public void handlePushEntry(TGzPushEntry tGzPushEntry) {

		// 先改为推送中
		tGzPushEntry.setFailReason("");
		tGzPushEntry.setPushTime(LocalDateTime.now());
		tGzPushEntry.setPushStatus(CommonConstants.THREE_STRING);
		tGzPushEntry.setUpdateTime(LocalDateTime.now());
		tGzPushEntryService.updateById(tGzPushEntry);

		// 判断推送任务: 如果任务类型是改状态的，直接获取任务记录里的数据推送
		if (ArrayUtils.contains(taskTypeArr, tGzPushEntry.getTaskType())) {
			// 状态推送任务
			this.pushStatusTask(tGzPushEntry);
		} else {
			// 97：档案信息推送，8：合同信息推送，99：合同附件推送
			if("97".equals(tGzPushEntry.getTaskType())){
				this.pushEmpTask(tGzPushEntry);
			}
			if("8".equals(tGzPushEntry.getTaskType())){
				this.pushContractTask(tGzPushEntry);
			}
			if("99".equals(tGzPushEntry.getTaskType())){
				this.pushContractAttaTask(tGzPushEntry);
			}
		}

		tGzPushEntry.setUpdateTime(LocalDateTime.now());
		tGzPushEntryService.updateById(tGzPushEntry);

		// 如果推送结果是成功，再获取【同一个流程ID最早一个未推送状态的数据】进行推送，
		// 推送成功更新数据，继续获取【同一个流程ID最早一个未推送状态的数据】
		if(CommonConstants.ZERO_STRING.equals(tGzPushEntry.getPushStatus())){
			this.pushWaitEntry(tGzPushEntry);
		}
	}

	/**
	 * 判断是否继续推 待推送
	 *
	 * @param tGzPushEntry 瓜子系统交互任务跟进表
	 * @return R
	 */
	private void pushWaitEntry(TGzPushEntry tGzPushEntry) {
		// 获取下一个待推送的数据
		TGzPushEntry findWaitInfo = tGzPushEntryService.getOne(Wrappers.<TGzPushEntry>query().lambda()
				.eq(TGzPushEntry::getBizId, tGzPushEntry.getBizId())
				.eq(TGzPushEntry::getPushStatus, CommonConstants.TWO_STRING)
				.eq(TGzPushEntry::getDelFlag, CommonConstants.ZERO_STRING)
				.orderByAsc(TGzPushEntry::getCreateTime)
				.last(CommonConstants.LAST_ONE_SQL));
		if (Common.isEmpty(findWaitInfo)) {
			return;
		}

		// 先改为推送中
		findWaitInfo.setFailReason("");
		findWaitInfo.setPushTime(LocalDateTime.now());
		findWaitInfo.setPushStatus(CommonConstants.THREE_STRING);
		findWaitInfo.setUpdateTime(LocalDateTime.now());
		tGzPushEntryService.updateById(findWaitInfo);

		// 如果任务类型是改状态的，直接获取任务记录里的数据推送
		if (ArrayUtils.contains(taskTypeArr, findWaitInfo.getTaskType())) {
			// 更新推送信息
			this.pushStatusTask(findWaitInfo);
		} else {
			// 如果任务类型是：推数据，重新获取档案里的数据推送
			// 97：档案信息推送，8：合同信息推送，99：合同附件推送
			if("97".equals(findWaitInfo.getTaskType())){
				this.pushEmpTask(findWaitInfo);
			}
			if("8".equals(findWaitInfo.getTaskType())){
				this.pushContractTask(findWaitInfo);
			}
			if("99".equals(findWaitInfo.getTaskType())){
				this.pushContractAttaTask(findWaitInfo);
			}
		}
		findWaitInfo.setUpdateBy(tGzPushEntry.getUpdateBy());
		findWaitInfo.setUpdateTime(LocalDateTime.now());
		tGzPushEntryService.updateById(findWaitInfo);

		// 推送成功更新数据，继续获取【同一个流程ID最早一个未推送状态的数据】
		if(CommonConstants.ZERO_STRING.equals(findWaitInfo.getPushStatus())){
			this.pushWaitEntry(findWaitInfo);
		}
	}

	/**
	 * 对接瓜子-进行状态任务推送
	 *
	 * @param pushInfo 瓜子系统交互任务跟进表
	 */
	private void pushStatusTask(TGzPushEntry pushInfo) {
		// 赋值传参
		Map<String, Object> params = new HashMap<>();
		params.put("bizId", pushInfo.getBizId());
		params.put("status", pushInfo.getTaskType());
		// 获取offer的信息，拿邮箱和手机号
		TGzOfferInfo findOffer = tGzOfferInfoMapper.selectOne(Wrappers.<TGzOfferInfo>query().lambda()
				.eq(TGzOfferInfo::getBizId, pushInfo.getBizId())
				.eq(TGzOfferInfo::getDelFlag, CommonConstants.ZERO_STRING)
				.last(CommonConstants.LAST_ONE_SQL));
		if(Common.isNotNull(findOffer)){
			params.put("phone", findOffer.getPhone());
			params.put("email", findOffer.getEmail());
		}

		// taskType == 13：待签署 推入职日期
		if(CommonConstants.THIRTEEN_STRING.equals(pushInfo.getTaskType())){
			params.put("entryDate", DateUtil.dateToString(findOffer.getExpEntryDate(),DateUtil.ISO_EXPANDED_DATE_FORMAT));
		}

		// 调瓜子接口
		Map<String,String> returnMap = gzConfig.updateGzOfferStatus(restTemplate, params);
		// 公共处理瓜子返回的信息
		this.handlePushReturnCommon(pushInfo, returnMap);
	}

	/**
	 * 对接瓜子-档案推送
	 *
	 * @param pushInfo 瓜子系统交互任务跟进表
	 */
	private void pushEmpTask(TGzPushEntry pushInfo) {
		// 根据流程ID获取档案信息
		TGzEmpInfo findEmpInfo = this.getEmpInfoCommon(pushInfo.getBizId());
		if (Common.isNotNull(findEmpInfo)) {
			// 调瓜子接口：获取档案附件，先上传档案附件给瓜子，再推档案信息

			// 1、获取档案附件
			List<TGzEmpInfoPushGzVoAtta> gzEmpAttaList = new ArrayList<>();

			List<TAttaInfo> aList = tAttaInfoService.list(Wrappers.<TAttaInfo>query().lambda()
					.eq(TAttaInfo::getDomainId, findEmpInfo.getId())
					.notIn(TAttaInfo::getRelationType, "41","42","43","CONTRACT"));
			if(Common.isNotNull(aList)){
				TGzEmpInfoPushGzFileVo vo;
				TGzEmpInfoPushGzVoAtta attaVo;

				String bizId = pushInfo.getBizId();
				String fileId;
				URL url;
				InputStream inStream = null;
				String base64String;

				for (TAttaInfo a : aList) {
					// 2、上传档案附件给瓜子
					if (Common.isNotNull(a.getAttaSrc())) {
						url = ossUtil.getObjectUrl(null, a.getAttaSrc());
						try {
							inStream = url.openStream();
							base64String = Base64.getEncoder().encodeToString(IOUtils.toByteArray(inStream));
							vo = new TGzEmpInfoPushGzFileVo();
							vo.setBizId(bizId);
							vo.setFileName(a.getAttaName());
							// 文件数据 Base64
							vo.setFileData(base64String);

							// 调瓜子上传附件接口，得到瓜子存储附件的ID
							fileId = gzConfig.pushGzFile(restTemplate, vo);

							// 组装档案附件列表
							attaVo = new TGzEmpInfoPushGzVoAtta();
							attaVo.setFileId(fileId);
							attaVo.setAttachType(a.getRelationType());
							attaVo.setFileName(a.getAttaName());
							gzEmpAttaList.add(attaVo);
						} catch (Exception e) {
							log.error("瓜子档案附件推送失败！", e);
						} finally {
							if (null != inStream) {
								try {
									inStream.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
			}

			// 3、获取档案信息
			TGzEmpInfoPushGzVo gzPushEmpInfo = tGzEmpInfoService.getGzEmpInfoToPushGzById(findEmpInfo.getId());
			gzPushEmpInfo.setAttach(gzEmpAttaList);
			// 4、推送瓜子档案
			Map<String,String> returnMap = gzConfig.pushGzEmpInfo(restTemplate, gzPushEmpInfo);

			// 公共处理瓜子返回的信息
			this.handlePushReturnCommon(pushInfo, returnMap);

			// 改档案里的【档案推送状态】为 已推送
			if(CommonConstants.GZ_SUCCESS_CODE.equals(returnMap.get("responseCode"))){
				LambdaUpdateWrapper<TGzEmpInfo> updateEmpWrapper = new LambdaUpdateWrapper<>();
				updateEmpWrapper.eq(TGzEmpInfo::getBizId, pushInfo.getBizId())
						.set(TGzEmpInfo::getEmpPushStatus, CommonConstants.ONE_STRING);
				tGzEmpInfoService.update(null, updateEmpWrapper);
			}
		}
	}

	/**
	 * 对接瓜子-合同信息推送
	 *
	 * @param pushInfo 瓜子系统交互任务跟进表
	 */
	private void pushContractTask(TGzPushEntry pushInfo) {
		// 根据流程ID获取档案信息
		TGzEmpInfo findEmpInfo = this.getEmpInfoCommon(pushInfo.getBizId());
		if (Common.isNotNull(findEmpInfo)) {
			// 调瓜子接口
			TGzEmpInfoPushGzContractVo gzPushContractInfo = tGzEmpInfoService.getGzEmpInfoToPushGzByIdContract(findEmpInfo.getId());
			Map<String,String> returnMap = gzConfig.pushGzEmpContract(restTemplate, gzPushContractInfo);

			// 公共处理瓜子返回的信息
			this.handlePushReturnCommon(pushInfo, returnMap);

			// 改档案里的【合同信息推送状态】状态为 已推送
			if(CommonConstants.GZ_SUCCESS_CODE.equals(returnMap.get("responseCode"))){
				LambdaUpdateWrapper<TGzEmpInfo> updateEmpWrapper = new LambdaUpdateWrapper<>();
				updateEmpWrapper.eq(TGzEmpInfo::getBizId, pushInfo.getBizId())
						.set(TGzEmpInfo::getContractPushStatus, CommonConstants.ONE_STRING);
				tGzEmpInfoService.update(null, updateEmpWrapper);
			}
		}
	}

	/**
	 * 根据流程ID获取瓜子档案信息
	 *
	 * @param bizId 瓜子流程ID
	 */
	private TGzEmpInfo getEmpInfoCommon(String bizId) {
		return tGzEmpInfoMapper.selectOne(Wrappers.<TGzEmpInfo>query().lambda()
					.eq(TGzEmpInfo::getBizId, bizId)
					.eq(TGzEmpInfo::getDelFlag, CommonConstants.ZERO_STRING)
					.last(CommonConstants.LAST_ONE_SQL));
	}

	/**
	 * 对接瓜子-合同附件推送
	 *
	 * @param pushInfo 瓜子系统交互任务跟进表
	 */
	private void pushContractAttaTask(TGzPushEntry pushInfo) {
		// 根据流程ID获取档案信息
		TGzEmpInfo findEmpInfo = this.getEmpInfoCommon(pushInfo.getBizId());
		if (Common.isEmpty(findEmpInfo)) {
			return;
		}

		// 调瓜子接口
		// 1、获取合同归档附件
		TAttaInfo contractAttaInfo = tAttaInfoService.getOne(Wrappers.<TAttaInfo>query().lambda()
				.eq(TAttaInfo::getDomainId, findEmpInfo.getId())
				.eq(TAttaInfo::getRelationType, "CONTRACT")
				.last(CommonConstants.LAST_ONE_SQL));
		if (Common.isEmpty(contractAttaInfo)) {
			return;
		}

		// 先上传附件，再推送atta与类型
		if (Common.isNotNull(contractAttaInfo.getAttaSrc())) {
			TGzEmpInfoPushGzFileVo pushGzFileVo;
			TGzEmpInfoPushGzAttaVo attaVo;

			String bizId = pushInfo.getBizId();
			String fileId;
			URL url;
			InputStream inStream = null;
			String base64String;

			// 获取合同附件
			url = ossUtil.getObjectUrl(null, contractAttaInfo.getAttaSrc());
			try {
				inStream = url.openStream();
				base64String = Base64.getEncoder().encodeToString(IOUtils.toByteArray(inStream));
				pushGzFileVo = new TGzEmpInfoPushGzFileVo();
				pushGzFileVo.setBizId(bizId);
				pushGzFileVo.setFileName(contractAttaInfo.getAttaName());
				// 文件数据 Base64
				pushGzFileVo.setFileData(base64String);

				// 2、先推合同附件文件给瓜子，得到瓜子存储附件的ID
				fileId = gzConfig.pushGzFile(restTemplate, pushGzFileVo);

				// 3、带着瓜子存储附件的ID 存合同附件
				attaVo = new TGzEmpInfoPushGzAttaVo();
				attaVo.setBizId(bizId);
				attaVo.setFileId(fileId);
				attaVo.setAttachType(contractAttaInfo.getRelationType());
				attaVo.setFileName(contractAttaInfo.getAttaName());

				Map<String,String> returnMap = gzConfig.pushGzAttach(restTemplate, attaVo);

				// 公共处理瓜子返回的信息
				this.handlePushReturnCommon(pushInfo, returnMap);

				// 改档案里的【合同附件推送状态】为 已推送
				if(CommonConstants.GZ_SUCCESS_CODE.equals(returnMap.get("responseCode"))){
					LambdaUpdateWrapper<TGzEmpInfo> updateEmpWrapper = new LambdaUpdateWrapper<>();
					updateEmpWrapper.eq(TGzEmpInfo::getBizId, pushInfo.getBizId())
							.set(TGzEmpInfo::getContractAttaPushStatus, CommonConstants.ONE_STRING);
					tGzEmpInfoService.update(null, updateEmpWrapper);
				}

			} catch (Exception e) {
				log.error("瓜子附件推送失败！");
				pushInfo.setPushStatus(CommonConstants.ONE_STRING);
				pushInfo.setFailReason("瓜子合同附件推送异常！");
			} finally {
				if (null != inStream) {
					try {
						inStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * 对接瓜子-公共处理瓜子返回的信息
	 *
	 * @param pushInfo 瓜子系统交互任务信息
	 * @param returnMap 瓜子响应信息
	 */
	private void handlePushReturnCommon(TGzPushEntry pushInfo, Map<String,String> returnMap){
		// 存推送报文
		pushInfo.setPushData(returnMap.get("pushData"));
		// 存响应结果
		pushInfo.setResponseData(returnMap.get("responseData"));

		// 默认推送成功
		pushInfo.setPushStatus(CommonConstants.ZERO_STRING);
		if(!CommonConstants.GZ_SUCCESS_CODE.equals(returnMap.get("responseCode"))){
			pushInfo.setPushStatus(CommonConstants.ONE_STRING);
			pushInfo.setFailReason(returnMap.get("responseMessage"));
		}
		pushInfo.setPushTime(LocalDateTime.now());
	}

}
