package com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
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.admin.api.entity.SysUser;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.SysUserListVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.SysUsersVo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TSettleDomain;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainListVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TSettleDomainRegistListVo;
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.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
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.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.SocialDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.config.WxConfig;
import com.yifu.cloud.plus.v1.yifu.insurances.constants.InsurancesConstants;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.SysConfig;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TInsuranceAlert;
import com.yifu.cloud.plus.v1.yifu.insurances.entity.TInsurancePreRenewDetail;
import com.yifu.cloud.plus.v1.yifu.insurances.mapper.insurances.SysConfigMapper;
import com.yifu.cloud.plus.v1.yifu.insurances.mapper.insurances.TInsuranceWarnMapper;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.TInsurancePreRenewDetailService;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.TInsuranceWarnService;
import com.yifu.cloud.plus.v1.yifu.insurances.util.LocalDateUtil;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.*;
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.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author huych
 * @description 针对表【t_insurance_alert(商险到期提醒表)】的数据库操作Service实现
 * @date 2024-08-26 14:20:16
 */
@Service
public class TInsuranceWarnServiceImpl extends ServiceImpl<TInsuranceWarnMapper, TInsuranceAlert> implements TInsuranceWarnService {
	@Autowired
	private UpmsDaprUtils upmsDaprUtils;
	@Autowired
	private ArchivesDaprUtil archivesDaprUtil;
	@Autowired
	private SocialDaprUtils socialDaprUtils;

	@Autowired
	private SysConfigMapper sysConfigMapper;
	@Autowired
	private TInsurancePreRenewDetailService tInsurancePreRenewDetailService;
	@Autowired
	private WxConfig wxConfig;

	@Override
	public IPage<TInsuranceAlert> getTInsuranceAlertPage(Page<TInsuranceAlert> page, TInsuranceAlertSearchVo tInsuranceAlert) {
		//权限赋值
		initSearchVo(tInsuranceAlert);
		return baseMapper.getTInsuranceAlertPage(page, tInsuranceAlert);
	}
	@Override
	public List<TInsuranceAlert> getTInsuranceAlertList2000(TInsuranceAlertSearchVo tInsuranceAlert) {
		//权限赋值
		initSearchVo(tInsuranceAlert);
		return baseMapper.getTInsuranceAlertList2000(tInsuranceAlert);
	}

	@Override
	public long getInsuranceAlertCount(TInsuranceAlertSearchVo tInsuranceAlert) {
		initSearchVo(tInsuranceAlert);
		return baseMapper.getTInsuranceAlertExportCount(tInsuranceAlert);
	}

	@Override
	public void exportTInsuranceAlert(TInsuranceAlertSearchVo searchVo, HttpServletResponse response) {
		String fileName = "商险待续保导出" + DateUtil.getThisTime() + CommonConstants.XLSX;
		//获取要导出的列表
		List<TInsuranceAlertExportVO> list = null;
		//获取要导出的列表
		if (Common.isNotNull(searchVo.getIdStr())) {
			searchVo.setIdList(Common.getList(searchVo.getIdStr()));
		}
		//权限赋值
		initSearchVo(searchVo);
		long count = baseMapper.getTInsuranceAlertExportCount(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, "UTF-8"));
			// 这里 需要指定写用哪个class去写，然后写到第一个sheet，然后文件流会自动关闭
			ExcelWriter excelWriter = EasyExcelFactory.write(out, TInsuranceAlertExportVO.class).build();
			int index = 0;
			if (count > CommonConstants.ZERO_INT) {
				WriteSheet writeSheet;
				for (int i = 0; i <= count; i += CommonConstants.EXCEL_EXPORT_LIMIT) {
					// 获取实际记录
					searchVo.setLimitStart(i);
					searchVo.setLimitEnd(CommonConstants.EXCEL_EXPORT_LIMIT);
					list = baseMapper.getTInsuranceAlertExport(searchVo);
					if (Common.isNotNull(list)) {
						writeSheet = EasyExcelFactory.writerSheet("商险待续保" + index).build();
						excelWriter.write(list, writeSheet);
						index++;
					}
				}
			} else {
				WriteSheet writeSheet = EasyExcelFactory.writerSheet("商险待续保导出" + index).build();
				excelWriter.write(list, writeSheet);
			}
			if (list != null && !list.isEmpty()) {
				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);
			}
		}
	}

	public void initSearchVo(TInsuranceAlertSearchVo 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 {
				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;
	}

	@Override
	public void createInsuranceAlert() {
		//批量删除所有未忽略的提醒数据
		baseMapper.delete(Wrappers.<TInsuranceAlert>query().lambda()
				.eq(TInsuranceAlert::getExpireIgnoreFlag, CommonConstants.ONE_STRING));
		//批量生成或者更新商险到期提醒数据
		List<TInsuranceAlert> list = baseMapper.selectInsuranceAlert();
		//获取所有在用的(未删除未锁定)MVP的用户信息
		String userIds;
		R<Set<String>> onlineSetTemp;
		if (Common.isNotKong(list)){
			try {
				SysConfig sysConfig = sysConfigMapper.getSysConfigLimitByKey(InsurancesConstants.INSURANCE_ALERT_DEFAULT_PERSON);
				userIds = list.stream().map(BaseEntity::getCreateBy).distinct().collect(Collectors.joining(","));
				// 获取停用账号信息
				Map<String, SysUser> userMap = null;
				// 前端客服对应的账号信息
				Map<String,SysUser> sysUserMap = null;
				//账号停用的提醒对应的项目信息
				Map<String, TSettleDomain> domainHashMap = new HashMap<>();
				userMap = getStopSysUserMap(userIds, userMap);
				//获取停用账户对应的项目的前端客服信息
				if (!Common.isEmpty(userMap)) {
					Map<String, SysUser> finalUserMap = userMap;
					List<String> codes = new ArrayList<>();
					list.stream().forEach(vo -> {
						if (Common.isNotNull(finalUserMap.get(vo.getCreateBy()))) {
							codes.add(vo.getDeptNo());
						}
					});
					if (Common.isNotKong(codes)) {
						//获取对应项目信息
						R<TSettleDomainListVo> infoByCodes = archivesDaprUtil.getSettleInfoByCodes(codes);
						if (null != infoByCodes && Common.isNotNull(infoByCodes.getData()) && Common.isNotNull(infoByCodes.getData().getMapVO())) {
							domainHashMap = infoByCodes.getData().getMapVO();
						}
						// 获取项目对应的前端客服用户信息
						sysUserMap = getStringSysUserMap(sysUserMap, domainHashMap);
					}
				}
				// 停用的账号的提醒信息对应的项目信息不为空 ，遍历更新 前端客服名称及前端客服ID
				initStopInfo(list, userMap, sysUserMap, domainHashMap,sysConfig);
			}catch (Exception e){
				log.error("商险不购买提醒初始化停用客服异常：",e);
			}
			//处理已经离职数据，分批请求，每次请求1000条数据，返回在职人员信息
			onlineSetTemp = new R<>();
			onlineSetTemp = getSetR(list, onlineSetTemp);
			//如果不存在离职人员直接走生成逻辑
			if (Common.isNotKong(onlineSetTemp.getData())){
				// 从 onlineSetTemp 中获取离职人员信息 删除list中已离职的数据
				removeLeaver(list, onlineSetTemp);

			}
			//不为空生成数据
			if (Common.isNotKong(list)){
				try {
					//获取假日信息
					R<HolidayListVO> holidayListR = socialDaprUtils.getOneMonthDay();
					Map<String, Integer> workDayMap = null;
					Map<String, Integer> holidayMap = null;
					if (null != holidayListR && Common.isNotNull(holidayListR.getData()) && Common.isNotNull(holidayListR.getData().getWorkDayMap())) {
						workDayMap = holidayListR.getData().getWorkDayMap();
						holidayMap = holidayListR.getData().getHolidayMap();
					}
					if (workDayMap != null && !workDayMap.isEmpty() && holidayMap != null && !holidayMap.isEmpty()) {
						String days;
						Integer dayInt;
						//获取自动化项目Map，后面放周期，默认1个月
						Map<String, AutoDeptDetailVO> deptMap = new HashMap<>();
						// 获取全量自动化项目，value里是续保周期
						R<AutoDeptVO> deptMapR = archivesDaprUtil.getAutoDeptVO();
						if (null != deptMapR && Common.isNotNull(deptMapR.getData()) && Common.isNotNull(deptMapR.getData().getDeptMap())) {
							deptMap = deptMapR.getData().getDeptMap();
						}
						List<TInsurancePreRenewDetail> detailList = new ArrayList<>();
						String renewId;
						// 处理：距离到期剩余工作日
						for (TInsuranceAlert vo : list) {
							if (Common.isNotNull(vo.getIsOverdue())
									&& CommonConstants.ZERO_INT == vo.getIsOverdue()
									&& Common.isNotNull(vo.getPolicyEnd())) {
								days = LocalDateUtil.getDateSrt(vo.getPolicyEnd(), LocalDateUtil.NORM_DATE_PATTERN);
								dayInt = workDayMap.get(days);
								if (Common.isNotNull(dayInt)) {
									vo.setHaveWorkDay(String.valueOf(dayInt));
								}

								// 为空，表示没有商险续签待办，需要新增
								// 自动化项目配置表中存在，则新增，否则不需要续签待办
								if (Common.isEmpty(vo.getInsurancesPreRenewDetailId())
										&& Common.isNotNull(vo.getDeptNo())
										&& deptMap.get(vo.getDeptNo()) != null) {
									renewId = String.valueOf(UUID.randomUUID()).replace("-", "");
									vo.setInsurancesPreRenewDetailId(renewId);

									// 生成续签待办数据
									this.setRenewDetailBaseInfo(vo, renewId, detailList, holidayMap, deptMap);

								}
							}
						}
						// 保存续签待办数据
						if (Common.isNotKong(detailList)) {
							tInsurancePreRenewDetailService.saveBatch(detailList);
						}
					}
				} catch (Exception e) {
					log.error("商险到期提醒获取工作日异常：",e);
				}
				this.saveOrUpdateBatch(list);
			}
		}

		//批量删除已忽略且人员离职的数据
		List<TInsuranceAlert> listIgnore = baseMapper.selectInsuranceAlertIgnore();
		onlineSetTemp = new R<>();
		onlineSetTemp = getSetR(listIgnore, onlineSetTemp);
		if (Common.isNotKong(onlineSetTemp.getData())){
			//批量删除已忽略且人员离职的数据
			baseMapper.delete(Wrappers.<TInsuranceAlert>query().lambda()
					.in(TInsuranceAlert::getEmpIdcardNo, onlineSetTemp.getData()));
		}
	}


	// 设置续签待办数据
	private void setRenewDetailBaseInfo(TInsuranceAlert vo, String renewId, List<TInsurancePreRenewDetail> detailList
			, Map<String, Integer> holidayMap, Map<String, AutoDeptDetailVO> deptMap) {
		TInsurancePreRenewDetail detail = new TInsurancePreRenewDetail();
		detail.setId(renewId);
		detail.setInsurancesId(vo.getId());
		detail.setDeptName(vo.getDeptName());
		detail.setDeptNo(vo.getDeptNo());
		detail.setEmpName(vo.getEmpName());
		detail.setEmpIdcardNo(vo.getEmpIdcardNo());
		detail.setPost(vo.getPost());
		detail.setBuyTypeOld(vo.getBuyType());
		detail.setInsuranceProvinceNameOld(vo.getInsuranceProvinceName());
		detail.setInsuranceCityNameOld(vo.getInsuranceCityName());
		detail.setInsuranceCompanyNameOld(vo.getInsuranceCompanyName());
		detail.setInsuranceTypeNameOld(vo.getInsuranceTypeName());
		detail.setPolicyEffectOld(vo.getPolicyEffect());
		detail.setPolicyStartOld(vo.getPolicyStart());
		detail.setPolicyEndOld(vo.getPolicyEnd());
		detail.setBuyType(CommonConstants.ONE_INT);
		detail.setConfigId(vo.getConfigId());
		detail.setConfigName(vo.getConfigName());
		detail.setInsuranceCompanyName(vo.getInsuranceCompanyName());
		detail.setInsuranceTypeName(vo.getInsuranceTypeName());
		detail.setBuyStandardOld(vo.getBuyStandard());
		detail.setBuyStandard(vo.getBuyStandard());
		detail.setInsuranceProvinceName(vo.getInsuranceProvinceName());
		detail.setInsuranceCityName(vo.getInsuranceCityName());
		AutoDeptDetailVO detailVO = deptMap.get(vo.getDeptNo());
		// 预计派单时间
		if (Common.isNotNull(vo.getPolicyEnd())) {
			detail.setPolicyStart(vo.getPolicyEnd().plusDays(CommonConstants.ONE_INT));
			detail.setPolicyEffect(detail.getPolicyStart());
			LocalDate days = calculateThreeWorkDays(vo.getPolicyEnd(), holidayMap);
			if (days != null && Common.isNotNull(days)) {
				// 新增逻辑
				detail.setExpectedCollectionTime(days.atTime(15, 20));

				Integer month = CommonConstants.ONE_INT;
				if (detailVO != null && Common.isNotNull(detailVO.getNum())) {
					month = detailVO.getNum();
				}
				if (Common.isEmpty(month)) {
					month = CommonConstants.ONE_INT;
				}
				detail.setPolicyEnd(this.doPolicyEnd(detail.getPolicyStart(), month));
				// 向前推2个工作日，作为确认发起时间的起点
				days = getPreviousWorkday(days, CommonConstants.TWO_INT, holidayMap);
				detail.setConfirmDate(days);
			}
		}
		if (detailVO != null) {
			detail.setCustomerUsername(detailVO.getCustomerUsername());
			detail.setCustomerUserLoginname(detailVO.getCustomerUserLoginame());
		}
		detail.setUnitName(vo.getUnitName());
		detail.setUnitNo(vo.getUnitNo());
		detail.setIsAddress(vo.getIsAddress());
		detail.setProcessStatus(CommonConstants.ZERO_STRING);

		detailList.add(detail);
	}

	// 保单截止日期，如果是1号：加一月减一天，如果不是1号：减一天加一月——不用这个逻辑了，倩倩与业务沟通后，统一：加月-1天
	private LocalDate doPolicyEnd(LocalDate policyStart, Integer month) {
		// 2025-11-14 09:46:13 倩倩：统一为：加一月减一天
		return policyStart
				.plusMonths(month)
				.minusDays(CommonConstants.ONE_INT);

	}

	// 保单截止日期B + 1天，向之前推3个工作日。得到预计派单日期
	private LocalDate calculateThreeWorkDays(LocalDate policyEnd, Map<String, Integer> holidayMap) {
		// 预计派单时间逻辑：
		//保单截止日期B + 1天，向之前推3个工作日。得到日期A。
		//如果A小于当前日期，则顺延到今天。
		//如果今天是工作日，则为今天。
		//如果今天非工作日，则顺延到工作日，如果超过B，则置空。

		// 步骤1: B + 1天，向前推3个工作日
		// 获取B + 1天
		LocalDate policyEndPlusDay = policyEnd.plusDays(1);
		// 向前推3个工作日
		LocalDate dateA = getPreviousWorkday(policyEndPlusDay, CommonConstants.THREE_INT, holidayMap);
		// 今天
		LocalDate today = LocalDate.now();
		// 步骤2: 如果A小于当前日期，则顺延
		if (dateA.isBefore(today)) {
			// 如果今天是工作日，则为今天
			if (this.isWorkday(today, holidayMap)) {
				return today;
			} else {
				// 今天非工作日，顺延到工作日
				return getNextWorkday(today, holidayMap);
			}
		}
		return dateA;
	}

	// 向前推N天工作日
	public LocalDate getPreviousWorkday(LocalDate date, int n, Map<String, Integer> holidayMap) {
		LocalDate result = date;
		int count = 0;
		while (count < n) {
			result = result.minusDays(CommonConstants.ONE_INT);
			if (this.isWorkday(result, holidayMap)) {
				count++;
			}
		}
		return result;
	}

	// 获取下一个工作日
	public LocalDate getNextWorkday(LocalDate date, Map<String, Integer> holidayMap) {
		LocalDate result = date.plusDays(CommonConstants.ONE_INT);
		while (!this.isWorkday(result, holidayMap)) {
			result = result.plusDays(CommonConstants.ONE_INT);
		}
		return result;
	}

	/**
	 * 判断是否为工作日,true是，false否
	 */
	public boolean isWorkday(LocalDate date, Map<String, Integer> holidayMap) {
		String days = LocalDateUtil.getDateSrt(date, LocalDateUtil.NORM_DATE_PATTERN);
		return holidayMap.get(days) == null;
	}

	private R<Set<String>> getSetR(List<TInsuranceAlert> list, R<Set<String>> onlineSetTemp) {
		if (list.size() <= 2000){
			onlineSetTemp = archivesDaprUtil.getEmpOnlineMap(list.stream().map(TInsuranceAlert::getEmpIdcardNo).collect(Collectors.toList()));
		}else {
			// 提前提取身份证号列表，避免重复 stream 操作
			List<String> idCardNoList = list.stream()
					.map(TInsuranceAlert::getEmpIdcardNo)
					.collect(Collectors.toList());

			int batchSize = 2000;
			int totalSize = idCardNoList.size();

			// 初始化 onlineSetTemp，防止 NullPointerException
			if (onlineSetTemp == null) {
				onlineSetTemp = new R<>(); // 替换为实际类型
			}
			R<Set<String>> onlineSet;
			Set<String> temp = new HashSet<>();

			for (int i = 0; i < totalSize; i++) {
				if (i % batchSize == 0) {
					// 计算当前批次的结束索引
					int end = Math.min(i + batchSize, totalSize);

					// 获取当前批次的数据
					List<String> subList = idCardNoList.subList(i, end);

					// 调用接口获取在职人员信息
					onlineSet = archivesDaprUtil.getEmpOnlineMap(subList);

					// 判空处理
					if (onlineSet != null && onlineSet.getData() != null && Common.isNotNull(onlineSet.getData())) {
						temp.addAll(onlineSet.getData());
					}
				}
			}
			if (temp != null){
				onlineSetTemp.setData(temp);
			}
		}
		return onlineSetTemp;
	}

	/**
	 * @Author fxj
	 * @Description  从 onlineSetTemp 中获取离职人员信息 删除list中已离职的数据
	 * @Date 14:24 2025/4/24
	 * @Param
	 * @return
	**/
	private void removeLeaver(List<TInsuranceAlert> list, R<Set<String>> onlineSetTemp) {
		// 边界条件检查
		if (list == null || list.isEmpty()) {
			return; // 如果列表为空或为 null，直接返回
		}
		// 使用 Iterator 安全地遍历并移除元素
		Iterator<TInsuranceAlert> iterator = list.iterator();
		Set<String> idCardSet = null;
		if (onlineSetTemp != null && onlineSetTemp.getData() != null) {
			idCardSet = new HashSet<>(onlineSetTemp.getData()); // 提高查找效率
		} else {
			idCardSet = new HashSet<>(); // 如果 onlineSetTemp 数据为空，初始化为空集合
		} // 提高查找效率
		while (iterator.hasNext()) {
			TInsuranceAlert vo = iterator.next();
			String empIdcardNo = vo.getEmpIdcardNo();
			// 如果身份证号存在于集合中，则移除该对象
			if (empIdcardNo != null && idCardSet.contains(empIdcardNo)) {
				iterator.remove();
			}
		}
	}

	/**
	 * @Author fxj
	 * @Description 获取停用账号信息
	 * @Date 19:09 2025/3/12
	**/
	private Map<String, SysUser> getStopSysUserMap(String userIds, Map<String, SysUser> userMap) {
		if (Common.isNotKong(userIds)){
			R<SysUsersVo> res = upmsDaprUtils.getUserVoByUserIds(userIds);
			if (Common.isNotNull(res) && Common.isNotNull(res.getData()) && Common.isNotNull(res.getData().getUserList())){
				userMap = res.getData().getUserList();
			}
		}
		return userMap;
	}

	/**
	 * @Author fxj
	 * @Description 根据项目编码CODES 获取项目前端客服用户信息
	 * @Date 19:07 2025/3/12
	**/
	private Map<String, SysUser> getStringSysUserMap(Map<String, SysUser> sysUserMap, Map<String, TSettleDomain> domainHashMap) {
		if (Common.isNotKong(domainHashMap)) {
			StringBuilder userNames = new StringBuilder();
			for (TSettleDomain val : domainHashMap.values()) {
				if (Common.isEmpty(userNames.toString())) {
					userNames.append(val.getCsLoginName());
				} else {
					userNames.append(CommonConstants.COMMA_STRING);
					userNames.append(val.getCsLoginName());
				}
			}
			if (!Common.isEmpty(userNames.toString())) {
				R<SysUserListVo> res = upmsDaprUtils.getUserIdsByUserNames(userNames.toString());
				List<SysUser> users = null;
				if (Common.isNotNull(res) && Common.isNotNull(res.getData()) && Common.isNotNull(res.getData().getUserList())) {
					users = res.getData().getUserList();
				}
				if (Common.isNotKong(users)) {
					sysUserMap = users.stream().collect(Collectors.toMap(k -> k.getUsername(), v -> v));
				}
			}
		}
		return sysUserMap;
	}

	/**
	 * @Author fxj
	 * @Description 封装停用账号为项目前端客服账号
	 * @Date 19:05 2025/3/12
	**/
	private void initStopInfo(List<TInsuranceAlert> list,
							  Map<String, SysUser> userMap,
							  Map<String, SysUser> sysUserMap,
							  Map<String, TSettleDomain> domainHashMap,
							  SysConfig sysConfig) {
		if (Common.isEmpty(userMap)){
			userMap = new HashMap<>();
		}
		if (Common.isNotKong(domainHashMap)){
			TSettleDomain domain;
			SysUser user;
			String loginName;
			String nickName;
			String userId;
			for (TInsuranceAlert alert: list){
				userId = null;
				nickName = null;
				alert.setAlertId(alert.getCreateBy());
				alert.setAlerter(alert.getCreateName());
				if (Common.isNotNull(userMap.get(alert.getCreateBy()))){
					domain = domainHashMap.get(alert.getDeptNo());
					if (Common.isNotNull(domain)){
						loginName = domain.getCsLoginName();
						if (Common.isNotNull(loginName)){
							user = null==sysUserMap?null:sysUserMap.get(loginName);
							if (Common.isNotNull(user) && !CommonConstants.NINE_STRING.equals(user.getLockFlag())){
								userId = user.getUserId();
								nickName = user.getNickname();
							}
						}
					}
					// 找不到对应前端客服或前端客服停用 发给徐瑞玲
					if (Common.isEmpty(userId) && Common.isNotNull(sysConfig)){
						userId = sysConfig.getConfigValue();
						nickName= sysConfig.getConfigValue1();
					}
					if (Common.isNotNull(nickName) && Common.isNotNull(userId)){
						alert.setAlerter(nickName);
						alert.setAlertId(userId);
					}
				}
			}
		}
	}
	/**
	 * @Author fxj
	 * @Description 每日09:00推送一条整合的待办数据——只推送前端客服，详情去HRO处理——消息待定：项目名称-项目编码、商险临期人数：**；商险过期人数：**；
	 * ——项目数：***、商险临期人数：***、商险过期人数：***，请及时至HRO系统进行处理，以免人员脱保！；
	 * @Date 18:55 2025/4/23
	 **/
	@Override
	public void pushInsuranceAlertToWx() {
		try {
			//先获取每个人的项目提醒信息
			List<InsuranceAlertWx> list = baseMapper.getInsuranceAlertToWx();
			if (Common.isNotKong(list)){
				Map<String, TSettleDomain> domainHashMap = null;
				Map<String, StringBuilder> pushMap = new HashMap<>();
				Map<String, SysUser> sysUserMap = new HashMap<>();
				List<String> codes = new ArrayList<>();
				list.stream().forEach(vo -> {
					codes.add(vo.getDeptNo());
				});
				if (Common.isNotKong(codes)) {
					//获取对应项目信息
					R<TSettleDomainListVo> infoByCodes = archivesDaprUtil.getSettleInfoByCodes(codes);
					if (null != infoByCodes && Common.isNotNull(infoByCodes.getData()) && Common.isNotNull(infoByCodes.getData().getMapVO())) {
						domainHashMap = infoByCodes.getData().getMapVO();
					}
				}
				sysUserMap = getMapInfo(domainHashMap, codes);
				//组装推送到企业微信的信息
				extracted(list, domainHashMap, pushMap, sysUserMap);
				//开始推送信息到企业微信
				if (Common.isNotKong(pushMap)){
					pushMap.forEach((k,v) -> {
						sendMessageToWx(k,v);
					});
				}
			}
		} catch (Exception e){
			log.error("推送商险待办信息到企业微信异常",e);
		}
	}
	/**
	 * @Author fxj
	 * @Description 组装推送到企业微信的信息
	 * @Date 20:20 2025/4/23
	**/
	private void extracted(List<InsuranceAlertWx> list, Map<String, TSettleDomain> domainHashMap,
						   Map<String, StringBuilder> pushMap,
						   Map<String, SysUser> sysUserMap) {
		if (Common.isNotNull(domainHashMap) && Common.isNotNull(sysUserMap)){
			TSettleDomain domain;
			SysUser user;
			StringBuilder content;
			Map<String, InsuranceAlertWxVo> tempMap = new HashMap<>();
			InsuranceAlertWxVo temp;
			String deptNo;
			//计算每个前端客服有多少个项目并保存到map
			Map<String,Integer> countMap = new HashMap<>();
			for (InsuranceAlertWx wx: list) {
				deptNo = wx.getDeptNo();
				if (Common.isEmpty(deptNo)) {
					continue; // 跳过无效的 deptNo
				}
				domain = domainHashMap.get(deptNo);
				if (Common.isEmpty(domain) || Common.isEmpty(domain.getCsLoginName())){
					continue;
				}
				String csLoginName = domain.getCsLoginName();
				countMap.put(csLoginName, countMap.getOrDefault(csLoginName, 0) + 1);
			}
			for (InsuranceAlertWx wx: list) {
				deptNo = wx.getDeptNo();
				if (Common.isEmpty(deptNo)) {
					continue; // 跳过无效的 deptNo
				}
				domain = domainHashMap.get(deptNo);
				if (Common.isEmpty(domain) || Common.isEmpty(domain.getCsLoginName())){
					continue;
				}
				user = sysUserMap.get(domain.getCsLoginName());
				if (Common.isEmpty(user) || Common.isEmpty(user.getWxMessage())) {
					continue; // 跳过无效的 user 或 wxMessage
				}
				temp = tempMap.computeIfAbsent(user.getWxMessage(), k -> new InsuranceAlertWxVo());
				temp.setDomainNum(countMap.get(domain.getCsLoginName()));
				temp.setGqNum(temp.getGqNum()+ Common.isEmptyToZero(wx.getGq()));
				temp.setLqNum(temp.getLqNum()+ Common.isEmptyToZero(wx.getLq()));
				tempMap.put(user.getWxMessage(), temp);
			}
			for (InsuranceAlertWx wx: list){
				deptNo = wx.getDeptNo();
				if (Common.isEmpty(deptNo)) {
					continue; // 跳过无效的 deptNo
				}
				domain = domainHashMap.get(deptNo);
				if (Common.isEmpty(domain)){
					continue;
				}
				user = sysUserMap.get(domain.getCsLoginName());
				if (Common.isEmpty(user) || Common.isEmpty(user.getWxMessage())) {
					continue; // 跳过无效的 user 或 wxMessage
				}
				temp = tempMap.get(user.getWxMessage());
				if (Common.isEmpty(temp)){
					continue;
				}
				if (CommonConstants.ZERO_STRING.equals(user.getLockFlag())
						&& CommonConstants.ZERO_STRING.equals(user.getDelFlag())){
					content = pushMap.get(user.getWxMessage());
					if (Common.isEmpty(content)){
						content = new StringBuilder();
						content.append(String.format("项目数：%d、商险临期人数：%d、商险过期人数：%d,<br/>",
						temp.getDomainNum(), temp.getLqNum(), temp.getGqNum()));						pushMap.put(user.getWxMessage(), content);
					}
				}
			}
		}
	}

	/**
	 * @Author fxj
	 * @Description  初始化 项目信息及项目对应用户信息
	 * @Date 19:49 2025/4/23
	**/
	private Map<String, SysUser> getMapInfo(Map<String, TSettleDomain> domainHashMap,
							List<String> codes) {
		Map<String, SysUser> sysUserMap = null;
		if (Common.isNotKong(codes)) {
			// 获取项目对应的前端客服用户信息--客服账号需要正常
			if (Common.isNotKong(domainHashMap)) {
				// 逗号拼接用户名，最后去除最后的逗号
				String userNames = domainHashMap.values().stream()
						.map(val -> val.getCsLoginName()) // 提取 CsLoginName
						.filter(name -> name != null)      // 过滤掉 null 值
						.collect(Collectors.toSet())      //去重
						.stream()
						.collect(Collectors.joining(CommonConstants.COMMA_STRING));
				if (userNames.length() > CommonConstants.ZERO_INT) {
					R<SysUserListVo> res = upmsDaprUtils.getUserIdsByUserNames(userNames);
					List<SysUser> users = null;
					if (Common.isNotNull(res) && Common.isNotNull(res.getData()) && Common.isNotNull(res.getData().getUserList())) {
						users = res.getData().getUserList();
					}
					if (Common.isNotKong(users)) {
						sysUserMap = users.stream().collect(Collectors.toMap(k -> k.getUsername(), v -> v));
					}
				}
			}
		}
		return sysUserMap;
	}
	//发送企业微信待办
	private void sendMessageToWx(String useruserWx, StringBuilder content) {
		if (Common.isEmpty(useruserWx) || Common.isEmpty(content)) {
			return;
		}
		StringBuilder sendUser = null;
		if (Common.isNotKong(useruserWx)) {
			sendUser = new StringBuilder(useruserWx);
		}
		if (sendUser != null) {
			RestTemplate restTemplate = new RestTemplate();
			Map<String, Object> requestMap = new HashMap<>();
			Map<String, Object> textcard = new HashMap<>();
			textcard.put("title", "商险待办提醒");
			textcard.put("url", String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "66" ));
			content.append("请及时至HRO系统进行处理，以免人员脱保！");
			textcard.put("description", content.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);
			}
		}
	}
}