/*
 *    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.ekp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.ekp.config.WxConfig;
import com.yifu.cloud.plus.v1.ekp.entity.EkpAlertTable;
import com.yifu.cloud.plus.v1.ekp.entity.EkpBudgetWarningInfo;
import com.yifu.cloud.plus.v1.ekp.mapper.EkpAlertTableMapper;
import com.yifu.cloud.plus.v1.ekp.mapper.EkpBudgetWarningInfoMapper;
import com.yifu.cloud.plus.v1.ekp.service.EkpAlertTableService;
import com.yifu.cloud.plus.v1.ekp.vo.BudgetWarningVo;
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.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.R;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import lombok.extern.log4j.Log4j2;
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 fxj
 * @date 2025-07-21 09:49:56
 */
@Log4j2
@Service
public class EkpAlertTableServiceImpl extends ServiceImpl<EkpAlertTableMapper, EkpAlertTable> implements EkpAlertTableService {
	@Autowired
	private WxConfig wxConfig;
	@Autowired
	private UpmsDaprUtils upmsDaprUtils;

	@Autowired
	private EkpBudgetWarningInfoMapper warningInfoMapper;



	/**
	 * @Author fxj
	 * @Description 推送企业微信消息
	 * @Date 15:29 2025/7/21
	**/
	private void pushInsuranceAlertToWx(List<BudgetWarningVo> vos) {
		try {
			if (Common.isNotKong(vos)){
				// 科目+二级成本中心 作为key 创建预警信息map
				Map<String, BudgetWarningVo> pushMap = new HashMap<>();
				// 科目+二级成本中心 作为key 创建用户信息map
				Map<String, List<SysUser>> sysUserMap = new HashMap<>();
				Map<String, List<String>> sysUserEkpMap = new HashMap<>();
				// 遍历预警信息列表，按科目+二级成本中心初始化Map
				for (BudgetWarningVo vo : vos) {
					// 创建组合键
					String key = vo.getKm() + "_" + vo.getCbzx();
					// 将预警信息放入Map中
					pushMap.put(key, vo);
					sysUserMap.putAll(getMapInfo(vo));
					sysUserEkpMap.putAll(getMapInfoEkp(vo));
				}
				//开始推送信息到企业微信
				if (Common.isNotKong(pushMap)  && Common.isNotNull(sysUserEkpMap)){
					List<SysUser> users;
					List<String> userIds;
					BudgetWarningVo config;
					String content;
					for (Map.Entry<String, BudgetWarningVo> entry : pushMap.entrySet()){
						users = sysUserMap.get(entry.getKey());
						userIds = sysUserEkpMap.get(entry.getKey());
						config = pushMap.get(entry.getKey());
						if (Common.isNotKong(config)){
							content = String.format("系统告警：%s 当前您所属的成本中心：%s下的%s预算余额剩余%s元，已不足%s%%，请关注预算使用情况。如有需要，可尽快追加预算，以免影响人员报销。",
									config.getAt(),
									config.getCbzx(),
									config.getKm(),
									config.getYe(),
									config.getFz(),
									config.getFz());
							// 处理推送信息保存
							hanlderWarning(users, config, content,userIds);
						}
					}
				}
			}
		} catch (Exception e){
			log.error("推送预算预警信息到企业微信异常",e);
		}
	}

	private void hanlderWarning(List<SysUser> users, BudgetWarningVo config, String content, List<String> userIds) {
		EkpBudgetWarningInfo warningInfo;
		HashMap<String,SysUser> userWxMap = new HashMap<>();
		if (Common.isNotKong(users)){
			for (SysUser user : users){
				userWxMap.put(user.getUsername(),user);
			}
		}
		if (Common.isNotKong(userIds)){
			SysUser userTemp;
			for (String userId : userIds){
				String[] temp = userId.split("_");
				if (temp.length > 1){
					userTemp =userWxMap.get(temp[0]);
					sendMessageToWx(null== userTemp?null:userTemp.getWxMessage(), content);
					warningInfo = new EkpBudgetWarningInfo();
					warningInfo.setFdContent(content);
					warningInfo.setFdReadStatus(CommonConstants.ZERO_STRING);
					warningInfo.setFdCreateTime(new Date());
					warningInfo.setFdSubject(config.getKm());
					warningInfo.setFdRecipientName(null== userTemp?null:userTemp.getNickname());
					warningInfo.setFdRecipientAccount(null== userTemp?temp[0]:userTemp.getUsername());
					warningInfo.setFdRecipientId(temp[1]);
					warningInfoMapper.insert(warningInfo);
				}
			}
		}
	}

	/**
	 * @Author fxj
	 * @Description  初始化 账号对应的用户信息
	 * @Date 19:49 2025/4/23
	 **/
	private Map<String, List<SysUser>> getMapInfo(BudgetWarningVo vo) {
		Map<String, List<SysUser>> sysUserMap = new HashMap<>();
		if (Common.isNotKong(vo) && Common.isNotKong(vo.getTxr())) {
			if (vo.getTxr().length() > CommonConstants.ZERO_INT) {
				R<SysUserListVo> res = upmsDaprUtils.getUserIdsByUserNames(getLoginNames(vo.getTxr()));
				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.put(vo.getKm() + "_" +vo.getCbzx(), users);
				}
			}
		}
		return sysUserMap;
	}
	private Map<String, List<String>> getMapInfoEkp(BudgetWarningVo vo) {
		Map<String, List<String>> map = new HashMap<>();
		if (Common.isNotKong(vo) && Common.isNotKong(vo.getTxr())) {
			List<String> loginNames = Arrays.stream(vo.getTxr().split(","))
					.filter(loginName -> !loginName.isEmpty())
					.collect(Collectors.toList());
			if (Common.isNotNull(loginNames)) {
				map.put(vo.getKm() + "_" +vo.getCbzx(), loginNames);
			}
		}
		return map;
	}
	private String getLoginNames(String txr) {
		//txr格式 loginName_id 获取到所有的loginName
		if (Common.isEmpty(txr)) {
			return txr;
		}
		return Arrays.stream(txr.split(","))
				.map(part -> part.split("_")[0])
				.filter(loginName -> !loginName.isEmpty())
				.collect(Collectors.joining( ","));
	}


	//发送企业微信待办
	private void sendMessageToWx(String useruserWx, String 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", "预算预警");
			// 传参77 企微详情提升“请至EKP系统处理！”
			textcard.put("url", String.format(SecurityConstants.WX_GET_MESSAGE_AUTH_URL, wxConfig.getCorpid(), wxConfig.getDomainName() + "/auth/oauth/wxLogin", "77" ));
			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);
			}
		}
	}

	/**
	 * @Author fxj
	 * @Description
	 * @Date 16:39 2025/7/21
	 * @Param type  0 按月  1 按日
	 * @return
	**/
	@Override
	public void pushBudgetAlertInfoTomanager(int type) {
		try {
			// 1. 获取当前时间
			LocalDateTime now = LocalDateTime.now();
			// 2. 查询所有有效的预警配置
			List<EkpAlertTable> alertSubjects = baseMapper.getEkpAlertTableList(type);
			// 3. 处理每个预警配置
			List<BudgetWarningVo> budgetWarningVos = new ArrayList<>();
			for (EkpAlertTable config : alertSubjects) {
				// 4. 判断是否满足执行条件
				if (shouldTriggerAlert(config,now,type)){
					// 5. 获取实际数据并判断是否达到阈值，符合条件则返回预警信息
					budgetWarningVos.addAll(isBudgetExceeded(config));
				}
			}
			if (Common.isNotNull(budgetWarningVos)) {
				// 6. 发送预警信息 + 记录预警信息
				pushInsuranceAlertToWx(budgetWarningVos);
			}
		} catch (Exception e) {
			log.error("执行预算预警任务时发生异常：", e);
		}
	}
	/**
	* @param config 预警配置
	* @return 是否超额
	*/
	private List<BudgetWarningVo> isBudgetExceeded(EkpAlertTable config) {
		List<BudgetWarningVo> resList = new ArrayList<>();
		if (null == config || null == config.getFdThresholdValue() || null == config.getFdAlertSubjectText()) {
			return resList;
		}
		//通过传参 科目获取需要预警的预算数据
		List<BudgetWarningVo> list = baseMapper.getBudgetWarningVos(config.getFdAlertSubjectText());
		if (Common.isNotKong(list)) {
			for (BudgetWarningVo vo : list) {
				//大于阀值且二级成本中心审核人不为空
				if (vo.getBl() >= Double.valueOf(config.getFdThresholdValue()) && Common.isNotNull(vo.getTxr())) {
					vo.setFz(100-(null==config.getFdThresholdValue()?0:config.getFdThresholdValue().intValue()));
					resList.add(vo);
				}
			}
		}
		return resList;
	}
	/**
	 * 检查预警是否应该触发
	 *
	 * @param config 预警配置
	 * @param currentDateTime 当前时间
	 * @return 是否应该触发预警
	 */
	private boolean shouldTriggerAlert(EkpAlertTable config, LocalDateTime currentDateTime,int type) {
		if (!"自动".equals(config.getFdDetectionMethod())){
			return false;
		}
		if (type == 1){
			// 处理按日配置
			if ("每日".equals(config.getFdChecktype())) {
				Date dailyTime = config.getFdEverydayTime(); // 获取每日执行时间
				if (dailyTime != null) {
					// 如果当前时间的小时 正好等于配置的时间的小时返回true
					return currentDateTime.getHour() == dailyTime.getHours();
				}
			}
		}{
			// 处理按日配置
			if ("每月".equals(config.getFdChecktype())) {
				if (null != config.getFdMonthday()) {
					// 当前日等于配置的日 返回 true
					return currentDateTime.getDayOfMonth() == config.getFdMonthday().intValue();
				}
			}
		}
		return false;
	}
}
