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

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.csp.entity.EmployeeRegistration;
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.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.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.log.util.SysLogUtils;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
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.mapper.insurances.SysConfigMapper;
import com.yifu.cloud.plus.v1.yifu.insurances.mapper.insurances.TInsuranceWarnMapper;
import com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.TInsuranceWarnService;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.InsuranceAlertWx;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.InsuranceAlertWxVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
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 SysConfigMapper sysConfigMapper;
	@Autowired
	private WxConfig wxConfig;
	@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)){
				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 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);
			}
		}
	}
}