package com.yeejoin.amos.patrol.business.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.transaction.Transactional;

import com.yeejoin.amos.patrol.business.feign.EquipFeign;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.google.common.base.Joiner;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.patrol.business.constants.XJConstant;
import com.yeejoin.amos.patrol.business.dao.mapper.MsgMapper;
import com.yeejoin.amos.patrol.business.dao.repository.IMsgDao;
import com.yeejoin.amos.patrol.business.dao.repository.IPlanTaskDetailDao;
import com.yeejoin.amos.patrol.business.dao.repository.IPointDao;
import com.yeejoin.amos.patrol.business.dao.repository.IRouteDao;
import com.yeejoin.amos.patrol.business.entity.mybatis.CheckMsgBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.PushTargetBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.TaskMsgBo;
import com.yeejoin.amos.patrol.business.param.MsgInfoPageParam;
import com.yeejoin.amos.patrol.business.param.NoticePublishParam;
import com.yeejoin.amos.patrol.business.param.PushMsgParam;
import com.yeejoin.amos.patrol.business.service.intfc.IMessageService;
import com.yeejoin.amos.patrol.business.util.StringUtil;
import com.yeejoin.amos.patrol.business.util.ToolUtils;
import com.yeejoin.amos.patrol.business.vo.MsgVo;
import com.yeejoin.amos.patrol.common.enums.CheckEmailEnum;
import com.yeejoin.amos.patrol.common.enums.CheckStatusEnum;
import com.yeejoin.amos.patrol.common.enums.CheckTypeEnum;
import com.yeejoin.amos.patrol.common.enums.JPushTypeEnum;
import com.yeejoin.amos.patrol.common.enums.MsgTypeEnum;
import com.yeejoin.amos.patrol.common.enums.PlanTaskDetailIsFinishEnum;
import com.yeejoin.amos.patrol.common.enums.PlanTaskFinishStatusEnum;
import com.yeejoin.amos.patrol.dao.entity.Msg;
import com.yeejoin.amos.patrol.dao.entity.PlanTask;
import com.yeejoin.amos.patrol.dao.entity.Point;
import com.yeejoin.amos.patrol.dao.entity.Route;
import com.yeejoin.amos.patrol.dao.entity.Task;
import com.yeejoin.amos.patrol.email.IEmailService;
import com.yeejoin.amos.patrol.feign.PushFeignServer;
import com.yeejoin.amos.patrol.feign.RemoteSecurityService;
import com.yeejoin.amos.patrol.jpush.AppMessagePushService;


/**
 * 消息推送
 * @author Administrator
 *
 */
@Service("messageService")
public class MessageServiceImpl implements IMessageService {

	private final Logger log = LoggerFactory.getLogger(MessageServiceImpl.class);

	@Autowired
	private MsgMapper msgMapper;

	@Autowired
	private IMsgDao iMsgDao;

	@Autowired
	private IPointDao iPointDao;

	@Autowired
	private IRouteDao iRouteDao;

	/*@Autowired
	private IUserDao iUserDao;*/

//	@Autowired
//	private IJobService jobService;

	@Autowired
	private IPlanTaskDetailDao planTaskDetailDao;

	@Autowired
	private IEmailService emailService;

	@Autowired
	private AppMessagePushService appMessagePushService;

	@Autowired
	private PushFeignServer  pushFeignServer;

	@Autowired
	private RemoteSecurityService remoteSecurityService;

	@Autowired
	private EquipFeign equipFeign;
	@Override
	public void pushCheckMessage(String toke,String product,String appKey,Long checkId) {
		try{
			//消息发送内容、执行人id，巡检点id，巡检线路id
			CheckMsgBo checkMsgBo = msgMapper.getCheckMsgBos(checkId);
			if(checkMsgBo != null){
				PushMsgParam pushMsgParam = new PushMsgParam();
				pushMsgParam.setContent(checkMsgBo.getPushMsg());
				pushMsgParam.setSubject(MsgTypeEnum.CHECK.getName());
				//发送目标，执行人，巡检点责任人，巡检线路责任人，关注线路人
				//获取建筑地址
				if(StringUtils.isNotBlank(checkMsgBo.getRiskSourceId())){
					LinkedHashMap<String,Object> positionAll  = equipFeign.getBuildingAbsolutePosition();
					LinkedHashMap<String,Object> position =  new LinkedHashMap<>();
					if("200".equals(positionAll.get("status").toString())){
						position = (LinkedHashMap<String, Object>) positionAll.get("result");
					}
					checkMsgBo.setPushMsg(checkMsgBo.getPushMsg().replace("address",position.get(checkMsgBo.getRiskSourceId()).toString()));
					checkMsgBo.setSaveMsg(checkMsgBo.getSaveMsg().replace("address",position.get(checkMsgBo.getRiskSourceId()).toString()));
				}else{
					checkMsgBo.setPushMsg(checkMsgBo.getPushMsg().replace("address","无"));
					checkMsgBo.setSaveMsg(checkMsgBo.getSaveMsg().replace("address","无"));
				}
				Set<String> needUserIds = new HashSet<>();
				//执行人
				needUserIds.add(checkMsgBo.getUserId());
				//获取点责任人
				Optional<Point> point = iPointDao.findById(checkMsgBo.getPointId());
				needUserIds.add(point.get().getChargePersonId());
				//获取线路责任人
				if(checkMsgBo.getRouteId() != 0){
					Optional<Route> route = iRouteDao.findById(checkMsgBo.getRouteId());
					if(route.isPresent()){
						if(route.get().getBoss() !=null && route.get().getBoss().trim() !=""){
							needUserIds.add(route.get().getBoss());
						}
					}
				}

				//获取需要推送的app的用户     手机端暂时无订阅功能，暂时屏蔽
//				List<PushTargetBo> jpushUser = msgMapper.getPushUserBo("app", String.join(",", needUserIds), checkMsgBo.getRouteId(),getAppPushConfig(checkMsgBo.getStatus()));
				List<PushTargetBo> jpushUser = new ArrayList<>();
				needUserIds.stream().forEach(action->{
					if(!ObjectUtils.isEmpty(action)){
						PushTargetBo pb = new PushTargetBo();
						pb.setUserId(action);
						jpushUser.add(pb);
					}
				});
				//获取需要推送的email的用户
				List<PushTargetBo> emailUser = msgMapper.getPushUserBo("email", String.join(",", needUserIds), checkMsgBo.getRouteId(),getEmailPushConfig(checkMsgBo.getStatus()));


				//处理用户信息
				List<PushTargetBo> tempList = new ArrayList<>();
				tempList.addAll(jpushUser);
				tempList.addAll(emailUser);
				// 手机端暂时无订阅功能，暂时屏蔽
//			   List<String> userIds=tempList.stream().map(PushTargetBo::getUserId).distinct().collect(Collectors.toList());
				Set<String> userIds = needUserIds;
	           List<AgencyUserModel> agencyUserModelList=remoteSecurityService.listUserByUserIds( toke,product,appKey,String.join(",", userIds));
				try {
					pushAppMsg(jpushUser,agencyUserModelList,pushMsgParam,checkMsgBo, toke, product, appKey);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					log.error(e.getMessage(), e);
					e.printStackTrace();
				}
				try {
					pushEmailMsg(emailUser, agencyUserModelList, pushMsgParam,checkMsgBo);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					log.error(e.getMessage(), e);
					e.printStackTrace();
				}
			}
		}catch (Exception e) {
			log.error(e.getMessage(), e);
			e.printStackTrace();
		}

	}



	private void pushEmailMsg(List<PushTargetBo> emailUser, List<AgencyUserModel> agencyUserModelList, PushMsgParam pushMsgParam,CheckMsgBo checkMsgBo) throws InterruptedException{

		 if(emailUser!=null && emailUser.size()>0){
			 emailUser.forEach(s -> {
        	   for(AgencyUserModel agencyUserModel:agencyUserModelList){
        		   if(s.getUserId().equals(agencyUserModel.getUserId())){
     	    			 s.setUsername(agencyUserModel.getUserName());
     	    			 s.setEmail(agencyUserModel.getEmail());
     	    		}
        	   }
       	    });
       }

		List<String> pushMails = emailUser.stream()
								.map(PushTargetBo::getEmail).collect(Collectors.toList());
		pushMails = pushMails.stream().filter(mail -> null != mail).distinct().collect(Collectors.toList());
		if(!pushMails.isEmpty()){
			String[] emails =pushMails.toArray(new String[pushMails.size()]);
			pushMsgParam.setEmails(emails);
			emailService.sendSimpleEmail(pushMsgParam.getEmails(), pushMsgParam.getSubject(), pushMsgParam.getContent());
		}
	}

	private void pushAppMsg(List<PushTargetBo> jpushUser,List<AgencyUserModel> agencyUserModelList,PushMsgParam pushMsgParam,CheckMsgBo checkMsgBo
			, String toke,String product,String appKey) throws InterruptedException{
		  //安全处里
		 if(jpushUser!=null&&jpushUser.size()>0){
			 jpushUser.forEach(s -> {
        	   for(AgencyUserModel agencyUserModel:agencyUserModelList){
        		   if(s.getUserId().equals(agencyUserModel.getUserId())){
     	    			 s.setUsername(agencyUserModel.getUserName());
     	    			 s.setName(agencyUserModel.getRealName());
     	    			 s.setUserId(agencyUserModel.getUserId());
     	    			 s.setEmail(agencyUserModel.getEmail());
     	    		}
        	   }
       	    });
       }

		List<String> pushApps = jpushUser.stream()
								.filter(bo->StringUtil.isNotEmpty(bo.getUserId()))
								.map(PushTargetBo::getUserId).collect(Collectors.toList());
		pushApps = pushApps.stream().distinct().collect(Collectors.toList());
		if(!pushApps.isEmpty()){
			List<PushMsgParam> pmps = new ArrayList<PushMsgParam>();
			pushMsgParam.setRecivers(pushApps);
			pushMsgParam.setType(JPushTypeEnum.ALIAS.getCode());
			Map<String, String> extras = new HashMap<String, String>();
			extras.put("type",MsgTypeEnum.CHECK.getCode());
			extras.put("id",checkMsgBo.getCheckId()+"");
			pushMsgParam.setExtras(extras);
			pushMsgParam.setRelationId(checkMsgBo.getCheckId()+"");
			pmps.add(pushMsgParam);
			List<Msg> msgList =createMsg(jpushUser,checkMsgBo);
			pushFeignServer.sendMessage( toke, product, appKey,pmps);

		}
	}

	/**
	 * 保存消失推送内容
	 * @param pushMsgAppInfoBos
	 * @param checkMsgBo
	 */
	private List createMsg(List<PushTargetBo> pushMsgAppInfoBos,CheckMsgBo checkMsgBo){
        pushMsgAppInfoBos=pushMsgAppInfoBos.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                     new TreeSet<>(Comparator.comparing(PushTargetBo::getUserId))), ArrayList::new));
		List<Msg> msgList = new ArrayList<Msg>();
        pushMsgAppInfoBos.forEach(action->{
			Msg msg = new Msg();
			msg.setTitle(MsgTypeEnum.CHECK.getName());
			msg.setBody(checkMsgBo.getSaveMsg());
			msg.setMsgType(MsgTypeEnum.CHECK.getCode());
			msg.setRelationId(checkMsgBo.getCheckId());
			msg.setReciverName(action.getName());
			msg.setRelationId(checkMsgBo.getCheckId());
			msg.setOrgCode(checkMsgBo.getOrgCode());
			msg.setRelationId(checkMsgBo.getCheckId());
			msg.setCreateDate(new Date());
			msg.setSendTime(new Date());
			msg.setUserId(action.getUserId());
			msg.setTargetTel(action.getUsername());
			msg.setStatus(1);
			msgList.add(msg);
		});
		return iMsgDao.saveAll(msgList);
	}


	private String getAppPushConfig(String checkStatus){
		String checkType =CheckTypeEnum.ALL.getCode();
		if(CheckStatusEnum.UNQUALIFIED.getCode().equals(checkStatus)){
			checkType = CheckTypeEnum.ERROR.getCode();
		}else if(CheckStatusEnum.OMISSION.getCode().equals(checkStatus)){
			checkType = CheckTypeEnum.LEAK.getCode();
		}
		return checkType;

	}

	private String getEmailPushConfig(String checkStatus){
		String checkType =CheckEmailEnum.ALL.getCode();
		if(CheckStatusEnum.UNQUALIFIED.getCode().equals(checkStatus)){
			checkType = CheckEmailEnum.ERROR.getCode();
		}else if(CheckStatusEnum.OMISSION.getCode().equals(checkStatus)){
			checkType = CheckEmailEnum.LEAK.getCode();
		}
		return checkType;

	}

	@Override
	public void pushTaskMessage(String toke,String product,String appKey,Task task) {
		//您好，您有一条名称为：my任务名称 内容为：my任务名称 说明 的任务单。要求完成时间为：2019-03-23 00:00:01 请您及时处理！任务下发人：18192060895
		TaskMsgBo taskMsgBo = msgMapper.getTaskMsgBos(task.getId());
//		pushMsgAndSaveMsg( toke, product, appKey,taskMsgBo,MsgTypeEnum.TASK.getName(),MsgTypeEnum.TASK.getCode(),true);
	}

	@Override
	public Msg pushMsgAndSave(String toke,String product,String appKey,Msg msg) {
		List<PushMsgParam> pmps = new ArrayList<PushMsgParam>();
		PushMsgParam pushMsg = new PushMsgParam();
		pushMsg.setRecivers(Arrays.asList(msg.getUserId()));
		pushMsg.setContent(ObjectUtils.isEmpty(msg.getPushBody()) ? msg.getBody() : msg.getPushBody());
		pushMsg.setSubject(msg.getTitle());
		pushMsg.setType(JPushTypeEnum.ALIAS.getCode());
		pushMsg.setRelationId(msg.getRelationId()==null?"0":msg.getRelationId().toString());
		Map<String, String> extras = new HashMap<String, String>();
		extras.put("type",msg.getMsgType());
		extras.put("id",msg.getRelationId()==null?"0":msg.getRelationId().toString());
		pushMsg.setExtras(extras);
		pmps.add(pushMsg);
		msg.setSendTime(new Date());
		msg.setStatus(1);
		pushFeignServer.sendMessage( toke, product, appKey,pmps);
		iMsgDao.save(msg);
		return msg;
	}

	@Override
	public Page<MsgVo> queryMsgInfoList(MsgInfoPageParam param) {
		long total = msgMapper.countMsgVoData(param);
		List<MsgVo> content = msgMapper.getMsgVoData(param);
		Page<MsgVo> result = new PageImpl<MsgVo>(content, param, total);
		return result;
	}

	@Override
	@Transactional
	public List<Msg> publishNotice(String toke,String product,String appKey,NoticePublishParam notice) {
		 List<String> userIds = notice.getUserId();
	        boolean isImmediately = notice.getIsImmediately();
	        List<Msg> msgList = new ArrayList<>();
	        List<AgencyUserModel> users = remoteSecurityService.listUserByUserIds(toke, product, appKey,Joiner.on(",").join(userIds));
	        for (AgencyUserModel user : users) {
	            String targetTel = user.getUserName();
	            Msg msg = new Msg();
	            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
	            String start = sdf.format(notice.getFixedTime());
	            msg.setBody(notice.getBody()+"\r\n发送时间:"+start);
	            msg.setIsImmediately(isImmediately);
	            msg.setMsgType(MsgTypeEnum.NOTIFY.getCode());
				msg.setOrgCode(notice.getOrgCode());
				msg.setTargetTel(targetTel);
				msg.setTitle(MsgTypeEnum.NOTIFY.getName());
				msg.setUserId(user.getUserId());
				msg.setReciverName(user.getRealName());
	            if (isImmediately) { //立即发送
	                msg = pushMsgAndSave( toke, product, appKey,msg);
	            } else { //定时发送
	                msg.setStatus(0);
	                msg.setFixedTime(notice.getFixedTime());

	                iMsgDao.save(msg);
	                msgList.add(msg);
	            }

	        }
	        return msgList;
	}

	@Override
	public void pushPlanTaskMessage(String toke,String product,String appKey,PlanTask planTask,String jobType) {
		// TODO Auto-generated method stub
		TaskMsgBo taskMsgBo = null;
		String title ="";
		String msgType = "";
		if(StringUtil.isNotEmpty(jobType)){
			if(jobType.contains(XJConstant.PLAN_TASK_WARN_MSG_PUSH)){
				 title = MsgTypeEnum.PLANWARN.getName();
				 msgType = MsgTypeEnum.PLANWARN.getCode();
				 taskMsgBo = msgMapper.getPlanTaskWarnMsgBos(planTask.getId());
			}else if(jobType.contains(XJConstant.PLAN_TASK_BEGIN_MSG_PUSH)){
				if(PlanTaskFinishStatusEnum.UNDERWAY.getValue() == planTask.getFinishStatus()){
//					List<Integer> status = new ArrayList<>();
//					status.add(PlanTaskDetailIsFinishEnum.FINISHED.getValue());
					int count = planTaskDetailDao.countByIsFinishAndTaskNo(PlanTaskDetailIsFinishEnum.FINISHED.getValue(),planTask.getId());
					if(count == 0){
						title = MsgTypeEnum.PLANBEGIN.getName();
						msgType = MsgTypeEnum.PLANBEGIN.getCode();
						taskMsgBo = msgMapper.getPlanTaskBeginMsgBos(planTask.getId());
					}
				}

			}else{
				title = MsgTypeEnum.PLANEND.getName();
				msgType = MsgTypeEnum.PLANEND.getCode();
				taskMsgBo = msgMapper.getPlanTaskEndMsgBos(planTask.getId());
			}
			pushMsgAndSaveMsg( toke, product, appKey,taskMsgBo,title,msgType,true);
		}

	}

	private void pushMsgAndSaveMsg(String toke,String product,String appKey,TaskMsgBo taskMsgBo,String title,String msgType,Boolean isImmediately){
		if(StringUtil.isNotEmpty(taskMsgBo)){
			List<AgencyUserModel> users = remoteSecurityService.listUserByUserIds(toke, product, appKey,taskMsgBo.getReciver());
			if(!users.isEmpty()){
				String userNames = users.stream().map(AgencyUserModel::getUserName).collect(Collectors.joining(","));
				String userIds = users.stream().map(AgencyUserModel::getUserId).collect(Collectors.joining(","));
				String reciverName = users.stream().map(AgencyUserModel::getRealName).collect(Collectors.joining(","));
				Msg msg = new Msg();
				msg.setTitle(title);
				msg.setBody(taskMsgBo.getSaveMsg());
				msg.setPushBody(taskMsgBo.getPushMsg());
				msg.setMsgType(msgType);
				msg.setReciverName(reciverName);
				msg.setRelationId(taskMsgBo.getTaskId());
				msg.setOrgCode(taskMsgBo.getOrgCode());
				msg.setTargetTel(userNames);
	            msg.setUserId(userIds);
				msg.setIsImmediately(isImmediately);
				pushMsgAndSave( toke, product, appKey,msg);
			}

		}
	}



	@Override
	public void pushMsg(String toke, String product, String appKey, PushMsgParam pmsg) {
		// TODO Auto-generated method stub
		pushFeignServer.sendMessage( toke, product, appKey,pmsg);
	}
}
