package com.yeejoin.amos.supervision.core.async;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.model.MessageModel;
import com.yeejoin.amos.supervision.business.dao.mapper.MsgSubscribeMapper;
import com.yeejoin.amos.supervision.business.dao.repository.IMsgDao;
import com.yeejoin.amos.supervision.business.entity.mybatis.MsgSubscribeBo;
import com.yeejoin.amos.supervision.business.param.PushMsgParam;
import com.yeejoin.amos.supervision.business.service.intfc.IMessageService;
import com.yeejoin.amos.supervision.business.service.intfc.ISafety3DDataSendService;
import com.yeejoin.amos.supervision.business.util.DateUtil;
import com.yeejoin.amos.supervision.business.util.Toke;
import com.yeejoin.amos.supervision.common.enums.JPushTypeEnum;
import com.yeejoin.amos.supervision.common.enums.MsgSubscribeEnum;
import com.yeejoin.amos.supervision.dao.entity.Msg;
import com.yeejoin.amos.supervision.dao.entity.Plan;
import com.yeejoin.amos.supervision.email.IEmailService;
import com.yeejoin.amos.supervision.feign.RemoteSecurityService;
import com.yeejoin.amos.supervision.jpush.AppMessagePushService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContextModel;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import java.util.*;
import java.util.concurrent.Future;

/**
 * 异步执行任务
 * @author Administrator
 *
 */
@Component
public class AsyncTask {
	private final Logger log = LoggerFactory.getLogger(AsyncTask.class);

	private final String msgType = "supervision";

	@Autowired
	private ISafety3DDataSendService safety3DDataSend;

	@Autowired
	private IMsgDao iMsgDao;

	@Autowired
	private IMessageService messageService;

	@Autowired
	private RemoteSecurityService remoteSecurityService;

	@Autowired
	private AppMessagePushService appMessagePushService;

	@Autowired
	private MsgSubscribeMapper msgSubscribeMapper;

	@Autowired
	private IEmailService iEmailService;

	private static final String TOKE = "TOKE";

	private static final String TAB = "\r\n";

	/**
	 * 邮件发送
	 * @param msgResponse
	 * @return
	 * @throws InterruptedException
	 */
//	@Async("asyncTaskExecutor")
//	public Future<Boolean> sendEmail(PushMsgParam pmp) throws InterruptedException {
//		  	long start = System.currentTimeMillis();
//	        iEmailService.sendSimpleEmail(pmp.getEmails(), pmp.getSubject(), pmp.getContent());
//	        long end = System.currentTimeMillis();
//	        log.info("=====邮件发送耗时："+(end-start)+"======");
//	        return new AsyncResult<Boolean>(true);
//	}
//
//	/**
//	 * jpush 推送
//	 * @param pmps
//	 * @return
//	 * @throws InterruptedException
//	 */
//	@Async("asyncTaskExecutor")
//    public Future<Boolean> sendJpush(List<PushMsgParam> pmps) throws InterruptedException {
//        long start = System.currentTimeMillis();
//        appMessagePushService.sendMessage(pmps);
//        long end = System.currentTimeMillis();
//        //返回true，告诉此任务已完成
//        log.info("=====Jpush发送耗时："+(end-start)+"======");
//        return new AsyncResult<Boolean>(true);
//    }

	/**
	 * 检查消息推送
	 * @param checkId
	 * @return
	 * @throws InterruptedException
	 */
	@Async("asyncTaskExecutor")
    public Future<Boolean> pushCheckInfoTo3D(Long checkId) throws InterruptedException {
		//巡检结果推送至业务
		safety3DDataSend.pointCheckInfoPushToB(checkId);
        return new AsyncResult<Boolean>(true);
    }

	/**
	 * 任务推送
	 * @param taskId
	 * @return
	 * @throws InterruptedException
	 */
	@Async("asyncTaskExecutor")
    public Future<Boolean> pushTaskDetailInfoTo3D(String toke,String product,String appKey,Long taskId) throws InterruptedException {
		safety3DDataSend.taskDetailInfoPush( toke, product, appKey,taskId);
        return new AsyncResult<Boolean>(true);
    }

	@Async("asyncTaskExecutor")
    public Future<Boolean> pushPointTo3D(String toke,String product,String appKey,List<Long> pointIds) throws InterruptedException {
		safety3DDataSend.pushPointTo3D( toke, product, appKey,pointIds);
        return new AsyncResult<Boolean>(true);
    }

	@Async("asyncTaskExecutor")
    public Future<Boolean> pushDeletePointTo3D(String toke,String product,String appKey,List<Long> pointIds) throws InterruptedException {
		safety3DDataSend.pushPointTo3D( toke, product, appKey,pointIds);
        return new AsyncResult<Boolean>(true);
    }

	@Async("asyncTaskExecutor")
    public Future<Boolean> pushRouteTo3D(String toke,String product,String appKey,List<Long> routeIds) throws InterruptedException {
		safety3DDataSend.pushRouteInfoTo3D( toke, product, appKey,routeIds);
        return new AsyncResult<Boolean>(true);
    }

	@Async("asyncTaskExecutor")
    public Future<Boolean> pushCheckMessage(Long checkId) throws InterruptedException {
    	Toke toke=  remoteSecurityService.getServerToken();
		messageService.pushCheckMessage(toke.getToke(),toke.getProduct(),toke.getAppKey(),checkId);
        return new AsyncResult<Boolean>(true);
    }

	/**
	 * 隐患待治理到期提醒
	 */
	@Async("asyncTaskExecutor")
	public void pushLatentDangerReformLimitDateExpireMessage(String informerList, String orgCode,
															 String latentDangerName, String reformLimitDate,
															 Long latentDangerId, Integer state,
															 String userRealName) {
//		if (CollectionUtils.isEmpty(receiverIds)) {
//			return;
//		}
		MsgSubscribeEnum msgTypeEnum = MsgSubscribeEnum.隐患治理推送;
		String body = "";
		body += "隐患治理提醒：您好，隐患治理即将到期，请及时处理！" + TAB;
		body += "隐患名称：" + latentDangerName + TAB;
		body += "治理日期：" + reformLimitDate;
		saveAndSendMsg(orgCode, informerList, msgTypeEnum.getTitle(), body, msgTypeEnum.getMsgType(), latentDangerId, state,userRealName);
	}

	/**
	 * 隐患治理
	 */
	@Async("asyncTaskExecutor")
	public void pushLatentDangerExecuteMessage(String informerList, String orgCode,
											   String latentDangerName, String pointName,
											   String exeDeptName, Long latentDangerId,
											   String exeUserRealName, String flowName,
											   String flowResult, String executeDate,
											   Integer state) {
		MsgSubscribeEnum msgTypeEnum = MsgSubscribeEnum.隐患治理推送;
		String body = "";
		body += executeDate + TAB;
		body += exeDeptName + " " + exeUserRealName + " " + flowName + "：" + flowResult + TAB;
		body += "隐患名称：" + latentDangerName + TAB;
		if (pointName != null) {
			body += "关联检查点：" + pointName + TAB;
		}
		saveAndSendMsg(orgCode, informerList, msgTypeEnum.getTitle(), body, msgTypeEnum.getMsgType(), latentDangerId, state,"");
	}

	/**
	 * 隐患验证通过
	 */
	@Async("asyncTaskExecutor")
	public void pushRiskWarnMessage(String informerList, String orgCode,
									String latentDangerName, Long riskFactorId,
									String riskFactorName, String pointName,
									String executeDate) {
//		if (CollectionUtils.isEmpty(sendUserIds)) {
//			return;
//		}
		MsgSubscribeEnum msgTypeEnum = MsgSubscribeEnum.风险评价提醒推送;
		String body = "";
		body += latentDangerName + "管控措施失效，隐患治理验证完毕,需重新进行风险评价！" + TAB;
		body += "关联危险源：" + pointName + TAB;
		body += "关联危险因素：" + riskFactorName + TAB;
		body += "执行时间：" + executeDate + TAB;
		if (pointName != null) {
			body += "关联检查点：" + pointName + TAB;
		}
		saveAndSendMsg(orgCode, informerList, msgTypeEnum.getTitle(), body, msgTypeEnum.getMsgType(), riskFactorId, null,"");
	}

	private void saveAndSendMsg(String orgCode, String informerList,
								String title, String body, String msgType,
								Long relationId, Integer state,
								String userRealName) {
		JSONArray array = JSONArray.parseArray(informerList);
		Set<String> sendUserIds = new HashSet<>();
		if (array.size()>0) {
			Date date = new Date();
			List<Msg> msgs = Lists.newArrayList();
			for (int i = 0; i <array.size() ; i++) {
				JSONObject user = array.getJSONObject(i);
				Msg msg = new Msg();
				msg.setOrgCode(orgCode);
				msg.setUserId(user.getString("userId"));
				msg.setTitle(title);
				msg.setBody(body);
				msg.setMsgType(msgType);
				msg.setRelationId(relationId);
				msg.setIsImmediately(true);
				msg.setSendTime(date);
				msg.setCreateDate(date);
				msg.setReciverName(user.getString("realName"));
				sendUserIds.add(user.getString("userId"));
				msgs.add(msg);
			}


			Map<String, String> extras = Maps.newHashMap();
			extras.put("type", msgType);
			extras.put("id", String.valueOf(relationId));
			if (state != null) {
				extras.put("state", String.valueOf(state));
			}
			PushMsgParam pushMsgParam = new PushMsgParam();
			pushMsgParam.setContent(body);
			pushMsgParam.setRecivers(Lists.newArrayList(sendUserIds));
			pushMsgParam.setSubject(title);
			pushMsgParam.setType(JPushTypeEnum.ALIAS.getCode());
			pushMsgParam.setExtras(extras);
			iMsgDao.saveAll(msgs);
			appMessagePushService.sendMessage(pushMsgParam);
//			log.info("极光推送成功====>" + sendUserIds);
		}
	}

	/**
	 * 风险研判
	 */
	@Async("asyncTaskExecutor")
	public void pushRiskJudgmentMessage(String informerList, String orgCode,
										String riskJudgmentName, String dataStr,
										String departmentName, String statusDesc,
										Long taskId, Integer state) {
//		if (CollectionUtils.isEmpty(sendUserIds)) {
//			return;
//		}
		JSONArray array = JSONArray.parseArray(informerList);
		Set<String> sendUserIds = new HashSet<>();
		for (int i = 0; i <array.size() ; i++) {
			sendUserIds.add(array.getJSONObject(i).getString("userId"));
		}

		MsgSubscribeEnum msgTypeEnum = MsgSubscribeEnum.风险研判推送;
		String body = "";
		body += riskJudgmentName + "：" + dataStr + TAB;
		body += departmentName + TAB;
		body += "状态：" + statusDesc + TAB;
		saveAndSendMsg(orgCode, informerList, msgTypeEnum.getTitle(), body, msgTypeEnum.getMsgType(), taskId, state,"");
		MsgSubscribeEnum eamilMsgTypeEnum = MsgSubscribeEnum.推送风险研判消息;
		Set<String> emailAfterFilterUserIds = userIdFilter(sendUserIds, eamilMsgTypeEnum.getMsgType());
		sendEmail(emailAfterFilterUserIds, msgTypeEnum.getTitle(), body);
	}

	private void sendEmail(Set<String> emailAfterFilterUserIds, String title, String body) {
		if (!CollectionUtils.isEmpty(emailAfterFilterUserIds)) {
			List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(Joiner.on(",").join(emailAfterFilterUserIds));
			List<String> emailList = Lists.newArrayList();
			for (AgencyUserModel user : userModels) {
				if (!StringUtils.isEmpty(user.getEmail())) {
					emailList.add(user.getEmail());
				}
			}
			String[] emailArr = new String[emailList.size()];
			emailList.toArray(emailArr);
			iEmailService.sendSimpleEmail(emailArr, title, body);
			log.info("邮箱推送成功====>" + emailList);
		}
	}

	/**
	 * 提交计划任务消息
	 * @param requestContextModel
	 * @param plan
	 * @param userIds 发送用户id集合
	 * @param isSendWeb 发送web标识
	 * @param isSendApp 发送app标识
	 */
	@Async
	public void sendAddPlanMsg(RequestContextModel requestContextModel, Plan plan, List<String> userIds, boolean isSendWeb, boolean isSendApp){
		MessageModel model = new MessageModel();
		model.setTitle(plan.getName());
		String body = String.format("计划名称：%s；检查类型：%s；创建时间：%s",
				plan.getName(), plan.getCheckTypeName(), DateUtil.date2LongStr(new Date()));
		model.setBody(body);
		try {
			model.setIsSendWeb(isSendWeb);
			model.setIsSendApp(isSendApp);
			model.setMsgType(msgType);
			model.setRelationId(String.valueOf(plan.getId()));
			model.setRecivers(userIds);
//			remoteSecurityService.addMessage(requestContextModel, model);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送消息至检查组长
	 * @param plan
	 */
	@Async
	public void sendPlanMsgToLeadPeople(RequestContextModel requestContextModel, Plan plan){
		MessageModel model = new MessageModel();
		model.setTitle(plan.getName());
		String body = String.format("计划名称：%s；检查类型：%s；创建时间：%s",
				plan.getName(), plan.getCheckTypeName(), DateUtil.date2LongStr(new Date()));
        model.setBody(body);
		String leadPeopleIds = plan.getLeadPeopleIds();
		if (!ValidationUtil.isEmpty(plan.getUserId()) && !leadPeopleIds.contains(plan.getUserId())){
			leadPeopleIds += "," + plan.getUserId();
		}
		try {
			List<String> recivers = remoteSecurityService.getAmosIdListByUserIds(requestContextModel, leadPeopleIds);
			model.setIsSendWeb(true);
			model.setIsSendApp(true);
			model.setMsgType(msgType);
			model.setRelationId(String.valueOf(plan.getId()));
			model.setRecivers(recivers);
//			remoteSecurityService.addMessage(requestContextModel, model);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送消息至检查组员
	 * @param plan
	 */
	@Async
	public void sendPlanMsg(RequestContextModel requestContextModel, Plan plan){
		MessageModel model = new MessageModel();
		model.setTitle(plan.getName());
		String body = String.format("计划名称：%s；检查类型：%s；创建时间：%s",
				plan.getName(), plan.getCheckTypeName(), DateUtil.date2LongStr(new Date()));
		model.setBody(body);
		String leadPeopleIds = plan.getLeadPeopleIds();
		if (!ValidationUtil.isEmpty(plan.getUserId()) && !leadPeopleIds.contains(plan.getUserId())){
			leadPeopleIds += "," + plan.getUserId();
		}
		try {
			List<String> recivers = remoteSecurityService.getAmosIdListByUserIds(requestContextModel, leadPeopleIds);
			model.setIsSendApp(true);
			model.setIsSendWeb(true);
			model.setMsgType(msgType);
			model.setRelationId(String.valueOf(plan.getId()));
			model.setRecivers(recivers);
			remoteSecurityService.addMessage(requestContextModel, model);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Set<String> userIdFilter(Set<String> sendUserIds, String msgType) {
		Set<String> afterFilterUserIds = Sets.newHashSet();
		if (CollectionUtils.isEmpty(sendUserIds)) {
			return afterFilterUserIds;
		}
		List<MsgSubscribeBo> msgSubscribeList = msgSubscribeMapper.listMsgSubscribeByTypeAndUserIds(msgType, sendUserIds);
		if (CollectionUtils.isEmpty(msgSubscribeList)) {
			return afterFilterUserIds;
		}
		Map<String, MsgSubscribeBo> msgSubscribeMap = Maps.uniqueIndex(msgSubscribeList, MsgSubscribeBo::getUserId);
		for (String userId : sendUserIds) {
			MsgSubscribeBo m = msgSubscribeMap.get(userId);
			if (m != null && m.getAttribute1().equals("True")) {
				afterFilterUserIds.add(m.getUserId());
			}
		}
		return afterFilterUserIds;
	}
}
