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

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.csp.vo.EmployeeRegistrationCustomerUserUpdateVo;
import com.yifu.cloud.plus.v1.csp.vo.TEmployeeContractDateVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysUser;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ClientNameConstants;
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.*;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.social.config.WxConfig;
import com.yifu.cloud.plus.v1.yifu.social.entity.TDispatchInfoPre;
import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialPreDetail;
import com.yifu.cloud.plus.v1.yifu.social.mapper.TDispatchInfoPreMapper;
import com.yifu.cloud.plus.v1.yifu.social.service.TDispatchInfoPreService;
import com.yifu.cloud.plus.v1.yifu.social.service.TDispatchInfoService;
import com.yifu.cloud.plus.v1.yifu.social.service.THolidayInfoService;
import com.yifu.cloud.plus.v1.yifu.social.service.TSocialPreDetailService;
import com.yifu.cloud.plus.v1.yifu.social.vo.TDispatchImportVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.TDispatchInfoPreExportVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.TDispatchInfoPreSearchVo;
import com.yifu.cloud.plus.v1.yifu.social.vo.TEmployeeInsuranceWorkDayVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 社保待购买表
 *
 * @author huych
 * @date 2025-09-30 16:40:07
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TDispatchInfoPreServiceImpl extends ServiceImpl<TDispatchInfoPreMapper, TDispatchInfoPre> implements TDispatchInfoPreService {

	@Autowired
	private ArchivesDaprUtil archivesDaprUtil;

	@Autowired
	private WxConfig wxConfig;

	@Autowired
	private UpmsDaprUtils upmsDaprUtils;

	private final TSocialPreDetailService socialPreDetailService;

	private final THolidayInfoService tHolidayInfoService;

	private final TDispatchInfoService dispatchInfoService;

	/**
     * 社保待购买表简单分页查询
     * @param tDispatchInfoPre 社保待购买表
     * @return
     */
    @Override
    public IPage<TDispatchInfoPre> getTDispatchInfoPrePage(Page<TDispatchInfoPre> page, TDispatchInfoPreSearchVo tDispatchInfoPre){
		//权限赋值
		initSearchVo(tDispatchInfoPre);
        return baseMapper.getTDispatchInfoPrePage(page,tDispatchInfoPre);
    }

    /**
     * 社保待购买表批量导出
     * @param searchVo 社保待购买表
     * @return
     */
    @Override
    public void listExport(HttpServletResponse response, TDispatchInfoPreSearchVo searchVo){
        String fileName = "社保待购买批量导出" + DateUtil.getThisTime() + ".xlsx";
        //获取要导出的列表
        List<TDispatchInfoPreExportVo> list = new ArrayList<>();
		initSearchVo(searchVo);
        long count = baseMapper.selectExportCount(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，然后文件流会自动关闭
            ExcelWriter excelWriter = EasyExcel.write(out, TDispatchInfoPreExportVo.class).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.selectExportList(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 List<TDispatchInfoPre> getNoPageList(TDispatchInfoPreSearchVo searchVo) {
		searchVo.setType(CommonConstants.ONE_STRING);
		initSearchVo(searchVo);
		if (Common.isEmpty(searchVo.getStatusList())) {
			searchVo.setStatusList(Stream.of("0").collect(Collectors.toList()));
		}
		return baseMapper.geNoPageList(searchVo);
	}

	@Override
	public R confirm(List<String> idList) {
		List<TDispatchInfoPre> socialPreList = baseMapper.selectList(Wrappers.<TDispatchInfoPre>query()
				.lambda().in(TDispatchInfoPre::getId, idList)
				.eq(TDispatchInfoPre::getProcessStatus, CommonConstants.ZERO_STRING));
		if (Common.isEmpty(socialPreList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		LambdaUpdateWrapper<TDispatchInfoPre> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.in(TDispatchInfoPre::getId,idList)
				.eq(TDispatchInfoPre::getProcessStatus, CommonConstants.ZERO_STRING)
				.set(TDispatchInfoPre::getProcessStatus, CommonConstants.ONE_STRING);
		this.update(updateWrapper);
		return R.ok();
	}

	@Override
	public long getDispatchInfoCount(TDispatchInfoPreSearchVo searchVo) {
		initSearchVo(searchVo);
		return baseMapper.selectExportCount(searchVo);
	}

	@Override
	public Boolean saveSocialPreInfo(EmployeeRegistrationPreVo registrationPreVo) {
		if (Common.isNotNull(registrationPreVo.getSocialIsBuy())
				&& registrationPreVo.getSocialIsBuy().equals(CommonConstants.ZERO_STRING)
				&& !registrationPreVo.getExitSocialInfoList().isEmpty()) {
			//删除已存在的入职确认信息对应的社保明细
			socialPreDetailService.remove(Wrappers.<TSocialPreDetail>lambdaQuery()
					.eq(TSocialPreDetail::getRegisterId, registrationPreVo.getExitSocialInfoList()
							.get(0).getRegisterId()));
			//批量新增
			for (TSocialPreDetailVo vo :registrationPreVo.getExitSocialInfoList()) {
				TSocialPreDetail preDetal = new TSocialPreDetail();
				BeanUtils.copyProperties(vo, preDetal);
				socialPreDetailService.save(preDetal);
			}
			//批量删除社保待购买列表中的待确认、待派单、派单失败、审核、办理失败的数据
			baseMapper.delete(Wrappers.<TDispatchInfoPre>query().lambda().in(
							TDispatchInfoPre::getProcessStatus,Arrays.asList("0", "1", "2", "4","8"))
							.eq(TDispatchInfoPre::getRegisterId,registrationPreVo.getExitSocialInfoList()
							.get(0).getRegisterId()));
		} else {
			//删除已存在的入职确认信息对应的社保明细
			TDispatchInfoPreVo preVo = registrationPreVo.getDispatchInfoPreVo();
			socialPreDetailService.remove(Wrappers.<TSocialPreDetail>lambdaQuery()
					.eq(TSocialPreDetail::getRegisterId, preVo.getRegisterId()));
			if (Common.isNotNull(preVo) && Common.isNotNull(preVo.getId())) {
				//更新逻辑
				TDispatchInfoPre pre = new TDispatchInfoPre();
				BeanUtils.copyProperties(preVo, pre);
				baseMapper.updateById(pre);
			}
			if (Common.isNotNull(preVo) && Common.isEmpty(preVo.getId())) {
				try {
					//判断是否存在社保待购买信息
					TDispatchInfoPre preExit = baseMapper.selectOne(Wrappers.<TDispatchInfoPre>query().lambda()
							.eq(TDispatchInfoPre::getRegisterId, preVo.getRegisterId())
							.eq(TDispatchInfoPre::getEmpIdcard, preVo.getEmpIdcard())
							.in(TDispatchInfoPre::getProcessStatus, Arrays.asList("0", "1", "2", "4","8"))
							.last(CommonConstants.LAST_ONE_SQL));
					TDispatchInfoPre pre = new TDispatchInfoPre();
					BeanUtils.copyProperties(preVo, pre);
					//时间格式转化
					if (Common.isNotNull(preVo.getExpectedCollectionTime())) {
						pre.setExpectedCollectionTime(LocalDateTimeUtils.dateToLocalDateTime(preVo.getExpectedCollectionTime()));
					}
					if (Common.isNotNull(preVo.getExpectedConfirmTime())) {
						pre.setExpectedConfirmTime(LocalDateTimeUtils.dateToLocalDateTime(preVo.getExpectedConfirmTime()));
					}
					if (Common.isEmpty(pre.getDispatchItem())) {
						preVo.setDispatchItem("养老、医疗、生育、失业、工伤、大病");
					}
					//如果自动触发派增为是，计算派单发起时间和派单确认时间
					if (Common.isNotNull(preVo.getIsAutoDis()) && CommonConstants.ZERO_STRING.equals(preVo.getIsAutoDis())
							&& Common.isNotNull(preVo.getExpectedCollectionType()) && Common.isEmpty(preVo.getExpectedCollectionTime())) {
						TEmployeeContractDateVo vo = new TEmployeeContractDateVo();
						vo.setMonthAfter(Integer.parseInt(preVo.getExpectedCollectionType()));
						vo.setYearAfter(0);
						vo.setRegistDate(preVo.getJoinLeaveDate());
						Date date = this.addYearsMonths(vo);
						TEmployeeInsuranceWorkDayVo dayVo = new TEmployeeInsuranceWorkDayVo();
						dayVo.setType(CommonConstants.TWO_STRING);
						dayVo.setRegistDate(date);
						dayVo.setRegistType(0);
						TEmployeeInsuranceWorkDayVo dataR = tHolidayInfoService.selectBeforeOrAfterWorkDayCommon(dayVo);
						if (Common.isNotNull(dataR) && Common.isNotNull(dataR.getPriDisDate())) {
							preVo.setExpectedCollectionTime(dataR.getRegistDate());
							preVo.setExpectedConfirmTime(dataR.getRegistDate());
						} else {
							preVo.setExpectedCollectionTime(date);
							preVo.setExpectedConfirmTime(date);
						}
						preVo.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
								preVo.getExpectedCollectionTime(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " 15:20", DateUtil.DATETIME_PATTERN_MINUTE));
						preVo.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
								preVo.getExpectedCollectionTime(), DateUtil.ISO_EXPANDED_DATE_FORMAT) + " 09:00", DateUtil.DATETIME_PATTERN_MINUTE));
					}
					if (Common.isNotNull(preExit)) {
						pre.setId(preExit.getId());
						baseMapper.deleteById(preExit);
					}
					baseMapper.insert(pre);
				} catch (Exception e) {
					log.error("执行异常", e);
					return false;
				}
			}
		}
		return true;
	}

	@Override
	public void updateSocialPreCustomerName(EmployeeRegistrationCustomerUserUpdateVo updateVo) {
		//批量更新前端客服名称
		if (Common.isNotNull(updateVo) && Common.isNotNull(updateVo.getDeptNo())) {
			LambdaUpdateWrapper<TDispatchInfoPre> updateWrapper = new LambdaUpdateWrapper<>();
			updateWrapper.eq(TDispatchInfoPre::getDeptNo, updateVo.getDeptNo())
					.set(TDispatchInfoPre::getCustomerUsername, updateVo.getCustomerUserName())
					.set(TDispatchInfoPre::getCustomerUserLoginName, updateVo.getCustomerUserLoginName());
			this.update(updateWrapper);
		}
	}

	@Override
	public EmployeePreSocialListVo getSocialPreInfoList(String id) {
		EmployeePreSocialListVo preSocialListVo = new EmployeePreSocialListVo();
		//获取社保已购买和待购买信息
		List<TSocialPreDetail> exitSocialInfoList = socialPreDetailService.list(Wrappers.<TSocialPreDetail>query().lambda()
				.eq(TSocialPreDetail::getRegisterId, id));
		if (Common.isNotNull(exitSocialInfoList) && !exitSocialInfoList.isEmpty()) {
			List<TSocialPreDetailVo> exitSocialInfoListVo = exitSocialInfoList.stream()
					.map(detail -> {
						TSocialPreDetailVo vo = new TSocialPreDetailVo();
						BeanUtils.copyProperties(detail, vo);
						return vo;
					})
					.collect(Collectors.toList());
			preSocialListVo.setExitSocialInfoList(exitSocialInfoListVo);
			return preSocialListVo;
		}
		TDispatchInfoPre preExit = baseMapper.selectOne(Wrappers.<TDispatchInfoPre>query().lambda()
				.eq(TDispatchInfoPre::getRegisterId, id)
				.last(CommonConstants.LAST_ONE_SQL));
		if (Common.isNotNull(preExit)) {
			TDispatchInfoPreVo pre = new TDispatchInfoPreVo();

			BeanUtils.copyProperties(preExit, pre);
			if (Common.isNotNull(preExit.getExpectedCollectionTime())) {
				pre.setExpectedCollectionTime(LocalDateTimeUtils.convertLDTToDate(preExit.getExpectedCollectionTime()));
				pre.setExpectedConfirmTime(LocalDateTimeUtils.convertLDTToDate(preExit.getExpectedConfirmTime()));
			}
			preSocialListVo.setDispatchInfoPreVo(pre);
		}
		return preSocialListVo;
	}

	@Override
	public EmployeePreSocialListVo getSocialPreInfoStatus(String id) {
		EmployeePreSocialListVo preSocialListVo = new EmployeePreSocialListVo();
		//获取社保已购买信息
		TDispatchInfoPre preExit = baseMapper.selectById(id);
		if (Common.isNotNull(preExit)) {
			TDispatchInfoPreVo pre = new TDispatchInfoPreVo();
			BeanUtils.copyProperties(preExit, pre);
			preSocialListVo.setDispatchInfoPreVo(pre);
		}
		return preSocialListVo;
	}

	@Override
	public void deleteUnProcessSocialPreInfo(String id) {
		//删除未处理的社保待购买信息
		this.remove(Wrappers.<TDispatchInfoPre>query().lambda()
				.in(TDispatchInfoPre::getProcessStatus, Arrays.asList("0", "1", "2", "4","8"))
				.eq(TDispatchInfoPre::getRegisterId, id));
	}


	@Override
	public R dispatcherSocial(List<String> idList,String type) {
		YifuUser user = SecurityUtils.getUser();
		List<TDispatchInfoPre> contractPreList = baseMapper.selectList(Wrappers.<TDispatchInfoPre>query()
				.lambda().in(TDispatchInfoPre::getId, idList)
				.in(TDispatchInfoPre::getProcessStatus, Arrays.asList("1","2","4","8","9")));
		// 如果没有找到任何未处理的社保待购买数据，返回失败消息
		if (Common.isEmpty(contractPreList)) {
			return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
		}
		//发起派单
		List<ErrorMessage> errorMessageListAll = new ArrayList<>();
		List<TDispatchImportVo> excelVOList = baseMapper.getDisPatcherSocialList(idList,Arrays.asList("1","2","4","8","9"),type);
		if (Common.isNotNull(excelVOList) && !excelVOList.isEmpty()) {
			List<TDispatchImportVo> disList;
			int k = 0;
			int i = (int) Math.ceil((double) excelVOList.size() / CommonConstants.INTEGER_HUNDRED);
			//前端客服对应的成功和失败数量
			Map<String,Integer> sumMap = new HashMap<>();
			Map<String,Integer> falureMap = new HashMap<>();
			// 先统计每个登录名的总派单数量
			for (TDispatchImportVo vo : excelVOList) {
				String preLoginName = vo.getPreLoginName();
				sumMap.put(preLoginName, sumMap.getOrDefault(preLoginName, 0) + 1);
				// 初始化失败数量为0
				falureMap.putIfAbsent(preLoginName, 0);
			}
			for (int j = 0; j < i; j++) {
				if (j == i - 1) {
					disList = excelVOList.subList(k, excelVOList.size());
				} else {
					disList = excelVOList.subList(k, k + 100);
				}
				k = k + 100;
				if (Common.isNotNull(disList)) {
					//调用批量派单接口100条处理一次，同原合同派单保持一致
					List<ErrorMessage> errorMessageList = new ArrayList<>();
					dispatchInfoService.importTDispatchInfo(disList, errorMessageList,user, null, new HashMap<>());
					if (!errorMessageList.stream().allMatch(message -> message.getMessage().equals(CommonConstants.SAVE_SUCCESS))) {
						errorMessageListAll.addAll(errorMessageList);
						//更新社保状态为2发起失败
						for (ErrorMessage errorMessage : errorMessageList) {
							if (!errorMessage.getMessage().equals(CommonConstants.SAVE_SUCCESS)) {
								TDispatchImportVo contractVO = disList.stream().filter(vo -> Objects.equals(
										vo.getRowIndex(), errorMessage.getLineNum())).collect(Collectors.toList()).get(0);
								LambdaUpdateWrapper<TDispatchInfoPre> updateWrapper = new LambdaUpdateWrapper<>();
								updateWrapper.in(TDispatchInfoPre::getId, contractVO.getPreId())
										.in(TDispatchInfoPre::getProcessStatus, Arrays.asList("1","2","4","8","9"))
										.set(TDispatchInfoPre::getProcessStatus, CommonConstants.TWO_STRING)
										.set(TDispatchInfoPre::getErrorInfo, errorMessage.getMessage())
										.set(TDispatchInfoPre::getErrorTime, LocalDateTimeUtils.convertLDToDate(LocalDate.now()));
								// 执行更新操作
								errorMessage.setData(contractVO);
								this.update(updateWrapper);
								// 统计失败数量
								String preLoginName = contractVO.getPreLoginName();
								falureMap.put(preLoginName, falureMap.getOrDefault(preLoginName, 0) + 1);
							}
						}
					}
				}
			}
			//针对定时任务派单的记录失败次数，集中提醒至该项目的“前端客服”
			if (!falureMap.isEmpty() && type.equals("2")) {
				for (Map.Entry<String, Integer> entry : falureMap.entrySet()) {
					String preLoginName = entry.getKey();
					int failureCount = entry.getValue();
					int sum = sumMap.get(preLoginName);
					sendDisFalureMessageToWx(preLoginName ,sum, failureCount);
				}

			}
		}
		return R.ok(errorMessageListAll);
	}

	@Override
	public void pushWxConfrimMessage() {
		//获取所有预计派单时间为当天而且状态是待确认的合同待签署数据
		List<TDispatchInfoPre> unConfirmList = baseMapper.getAllUnDisData();
		if (Common.isNotNull(unConfirmList) && !unConfirmList.isEmpty()) {
			for (TDispatchInfoPre pre : unConfirmList) {
				try {
					sendMessageToWx(pre);
				} catch (Exception e) {
					log.error("执行异常", e);
				}
			}
		}
	}

	@Override
	public void pushDisConfrimSocial() {
		//获取所有待派单的数据
		List<String> unConfirmList = baseMapper.getAllUnDisDataIdList();
		if (null != unConfirmList && !unConfirmList.isEmpty()) {
			try {
				this.dispatcherSocial(unConfirmList,"2");
			} catch (Exception e) {
				log.error("执行异常", e);
			}
		}
	}

	//发送企业微信待办
	private void sendMessageToWx(TDispatchInfoPre pre) {
		//获取前端客服
		SysUser user;
		if (Common.isEmpty(pre.getCustomerUserLoginName())) {
			return;
		}
		R<SysUser> res = upmsDaprUtils.getSimpleUserByLoginName(pre.getCustomerUserLoginName());
		if (Common.isNotNull(res) && Common.isNotNull(res.getData())) {
			user = res.getData();
		} else {
			return;
		}
		StringBuilder sendUser = null;
		if (Common.isNotKong(user.getWxMessage())) {
			sendUser = new StringBuilder(user.getWxMessage());
		}
		if (sendUser != null) {
			RestTemplate restTemplate = new RestTemplate();
			Map<String, Object> requestMap = new HashMap<>();
			Map<String, Object> textcard = new HashMap<>();
			String authUrl = String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "04" + pre.getCustomerUserLoginName());
			StringBuilder description = new StringBuilder();
			String title = "社保购买确认";
			description.append("您有新的社保待购买确认数据，请及时确认").append("<br>");
			textcard.put("title", title);
			textcard.put("url", authUrl);
			textcard.put("description", description.toString());
			requestMap.put("touser", sendUser);
			requestMap.put("agentid", wxConfig.getAgentid());
			requestMap.put("msgtype", "textcard");
			requestMap.put("textcard", textcard);
			// 必须加上header说明
			if (!wxConfig.sendTextCard(restTemplate, requestMap)) {
				wxConfig.sendTextCard(restTemplate, requestMap);
			}
		}
	}

	//发送企业微信待办
	private void sendDisFalureMessageToWx(String LoginName, int sum, int falureNum) {
		//获取前端客服
		SysUser user;
		if (Common.isEmpty(LoginName)) {
			return;
		}
		R<SysUser> res = upmsDaprUtils.getSimpleUserByLoginName(LoginName);
		if (Common.isNotNull(res) && Common.isNotNull(res.getData())) {
			user = res.getData();
		} else {
			return;
		}
		StringBuilder sendUser = null;
		if (Common.isNotKong(user.getWxMessage())) {
			sendUser = new StringBuilder(user.getWxMessage());
		}
		if (sendUser != null) {
			RestTemplate restTemplate = new RestTemplate();
			Map<String, Object> requestMap = new HashMap<>();
			Map<String, Object> textcard = new HashMap<>();
			String authUrl = String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "67" + LoginName);
			StringBuilder description = new StringBuilder();
			String title = "作业自动化——社保派单发起失败提醒";
			description.append("社保派单数：").append(sum).append("份，失败份数：").append(falureNum).append("份；").append("<br>");
			description.append("点击查看详情").append("<br>");
			description.append("<br>");
			description.append("请及时至HRO系统处理，以免耽误购买进度！").append("<br>");
			textcard.put("title", title);
			textcard.put("url", authUrl);
			textcard.put("description", description.toString());
			requestMap.put("touser", sendUser);
			requestMap.put("agentid", wxConfig.getAgentid());
			requestMap.put("msgtype", "textcard");
			requestMap.put("textcard", textcard);
			// 必须加上header说明
			if (!wxConfig.sendTextCard(restTemplate, requestMap)) {
				wxConfig.sendTextCard(restTemplate, requestMap);
			}
		}
	}

	/**
	 * @Description: 获取前端客服的所有项目权限
	 * @Author: huych
	 * @Date: 2025/3/13 17:02
	 * @return:
	 **/
	public void initSearchVo(TDispatchInfoPreSearchVo 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);
			//获取项目信息
			R<TSettleDomainRegistListVo> domainR = archivesDaprUtil.getAllDeptByCustomerLoginName(user.getUsername());
			if (null != domainR && null != domainR.getData() && null != domainR.getData().getDeptNos() && !domainR.getData().getDeptNos().isEmpty()) {
				searchVo.setDeptNoList(domainR.getData().getDeptNos());
			} 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;
	}

	public Date addYearsMonths(TEmployeeContractDateVo vo) {
		if (vo == null || vo.getRegistDate() == null) return null;

		// 转换为LocalDate（自动处理时区）
		LocalDate localDate = vo.getRegistDate().toInstant()
				.atZone(ZoneId.systemDefault())
				.toLocalDate();
		// 添加年数和月数
		localDate = localDate
				.plusYears(vo.getYearAfter())
				.plusMonths(vo.getMonthAfter())
				.minusDays(1);
		// 转回Date类型
		return Date.from(localDate.atStartOfDay()
				.atZone(ZoneId.systemDefault())
				.toInstant());
	}
}
