package com.yeejoin.amos.patrol.quartz;

import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.DepartmentModel;
import com.yeejoin.amos.patrol.business.constants.XJConstant;
import com.yeejoin.amos.patrol.business.dao.mapper.*;
import com.yeejoin.amos.patrol.business.dao.mapper.MsgMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.PlanTaskMapper;
import com.yeejoin.amos.patrol.business.dao.repository.*;
import com.yeejoin.amos.patrol.business.entity.mybatis.PlanTaskPointInputItemBo;
import com.yeejoin.amos.patrol.business.param.MsgConfigParam;
import com.yeejoin.amos.patrol.business.service.intfc.IMessageService;
import com.yeejoin.amos.patrol.business.util.DateUtil;
import com.yeejoin.amos.patrol.business.util.Toke;
import com.yeejoin.amos.patrol.common.enums.*;
import com.yeejoin.amos.patrol.core.async.AsyncTask;
import com.yeejoin.amos.patrol.dao.entity.*;
import com.yeejoin.amos.patrol.feign.RemoteSecurityService;
import com.yeejoin.amos.patrol.mqtt.WebMqttComponent;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.Job;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("jobService")
public class JobService implements IJobService {

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

	@Autowired
	private ITaskDao iTaskDao;

	@Autowired
	private IPlanTaskDao iPlanTaskDao;

	@Autowired
	private IPlanDao iPlanDao;

	@Autowired
	private IPlanTaskDetailDao iPlanTaskDetailDao;

	@Autowired
	private IMessageService messageService;

	@Autowired
	private PlanTaskMapper planTaskMapper;

	@Autowired
	private MsgMapper msgMapper;

	@Autowired
	private ICheckDao iCheckDao;

	@Autowired
	private ICheckInputDao iCheckInputDao;

	@Autowired
	private AsyncTask asyncTask;

	@Autowired
	private IMsgDao iMsgDao;

	@Autowired
	private ITaskFeedbackDao taskFeedbackDao;

	@Autowired
	private CheckMapper checkMapper;
	@Autowired
    private RemoteSecurityService remoteSecurityService;

	@Value("${amosRefresh.patrol.topic}")
	private String patrolTopic;
	@Autowired
	private WebMqttComponent webMqttComponent;
	@Override
	@Transactional
	public void initScheduler() {
		// TODO Auto-generated method stub
		log.debug("======================initScheduler===========================");
		initTaskJob();
		initPlanTaskJob();
		initMsgJob();
	}

	@Override
	public void addJob(String name, String jobType, long id, Date time) {
		String jobName = name + "-" + jobType + "-" + id;
		if (time != null && time.getTime() > new Date().getTime()) {
			SimpleDateFormat formatter = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
			String cronDate = formatter.format(time);
			log.debug("addJob==jobName==" + jobName);
			QuartzManager.addJob(jobName, jobType, id, getJobInstance(name).getClass(), cronDate);
		}
	}

	/**
	 * 初始化任务job
	 */
	private void initTaskJob() {
		List<Task> taskList = iTaskDao.findAllByStatus(TaskStatusEnum.UNDERWAY.getValue());
		List<Task> updateTask = new ArrayList<Task>();
		taskList.forEach(task -> {
			Date finishTime = task.getFinishTime();
			if (finishTime != null) {
				if (finishTime.getTime() > new Date().getTime()) {
					taskAddJob(task);
				} else {
					task.setStatus(TaskStatusEnum.OVERTIME.getValue());
					updateTask.add(task);
				}
			}
		});
		iTaskDao.saveAll(updateTask);
	}

	/**
	 * 初始化计划执行job
	 */
	private void initPlanTaskJob() {
		List<Integer> statusList = new ArrayList<Integer>();
		statusList.add(PlanTaskFinishStatusEnum.NOTSTARTED.getValue());
		statusList.add(PlanTaskFinishStatusEnum.UNDERWAY.getValue());
		List<PlanTask> planTaskList = iPlanTaskDao.findAllByFinishStatusIn(statusList);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		planTaskList.forEach(planTask -> {
			try {
				Date beginTime = sdf.parse(planTask.getBeginTime());
				Date endTime = sdf.parse(planTask.getEndTime());
				long timestamp = new Date().getTime();
				if (PlanTaskFinishStatusEnum.NOTSTARTED.getValue() == planTask.getFinishStatus()) {
					if (beginTime.getTime() > timestamp) {
						planTaskAddJob(planTask);

					} else if (beginTime.getTime() < timestamp && endTime.getTime() > timestamp) {
						planTask.setFinishStatus(PlanTaskFinishStatusEnum.UNDERWAY.getValue());
						iPlanTaskDao.save(planTask);
						planTaskAddJob(planTask);
					} else if (endTime.getTime() < timestamp) {
						updatePlanTaskStatus(planTask, PlanTaskFinishStatusEnum.OVERTIME.getValue());
					}
				} else {
					if (endTime.getTime() < timestamp) {
						updatePlanTaskStatus(planTask, PlanTaskFinishStatusEnum.OVERTIME.getValue());
					} else {
						planTaskAddJob(planTask);
					}
				}
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				log.debug(e.getMessage());
				e.printStackTrace();
			}
		});

	}

	private void initMsgJob() {
		List<Msg> msgList = iMsgDao.findAllByIsImmediatelyTrueAndStatus(0);
		if (!msgList.isEmpty()) {
			msgList.forEach(msg -> {
				addJob("msg", XJConstant.MESSAGE_PUSH, msg.getId(), msg.getFixedTime());
			});
		}
	}

	private void updatePlanTaskStatus(PlanTask planTask, int status) {
		planTask.setFinishStatus(status);
		iPlanTaskDao.save(planTask);
		List<PlanTaskDetail> planTaskDetails = iPlanTaskDetailDao.findAllByTaskNoAndStatus(planTask.getId(),PlanTaskDetailStatusEnum.NOTSTARTED.getValue());
		if (!planTaskDetails.isEmpty()) {
			planTaskDetails.stream()
					.forEach(action -> {
						action.setIsFinish(PlanTaskDetailIsFinishEnum.OVERTIME.getValue());
						action.setStatus(PlanTaskDetailStatusEnum.OMISSION.getValue());
						iPlanTaskDetailDao.saveAndFlush(action);
					});
		}
		if (PlanTaskFinishStatusEnum.OVERTIME.getValue() == status) {
			createOmissionCheckRecord(planTask);
		}
	}

	/**
	 * 创建漏检检查记录
	 *
	 * @param planTask
	 */
	private void createOmissionCheckRecord(PlanTask planTask) {
		List<PlanTaskPointInputItemBo> planTaskPointInputItems = planTaskMapper
				.getPlanTaskPointInputItemByPlanTaskId(planTask.getId(),PlanTaskDetailStatusEnum.OMISSION.getValue());
		Map<Long, Check> checkMap = new HashMap<>();
		Set<Long> checkIds = new HashSet<Long>();
		Map<String,String> deptMap =new HashMap<>();
        Toke  toke=  remoteSecurityService.getServerToken();
		//查询用户名字

		//修改巡检p_plan_task orgcode为执行人的org_coed   -- add by wujunkai 20201216
		String userIds="";
		StringBuffer deptName = new StringBuffer();
		StringBuffer deptId = new StringBuffer();
		StringBuffer userName = new StringBuffer();
		if(planTask.getUserDept().indexOf(",")>0){
			List<String>  ids =  Arrays.asList(planTask.getUserId().split(","));
			List<String>  depts =  Arrays.asList(planTask.getUserDept().split(","));
			depts.stream().forEach(dept->{
				deptMap.put(dept.substring(0,dept.indexOf("@")),dept.substring(dept.indexOf("@")+1));
				deptId.append(dept.substring(dept.indexOf("@")+1)).append(",");
			});
			Set<String> departmentOrgCode= new HashSet<>();
			for (String key:deptMap.keySet()) {
				departmentOrgCode.add(deptMap.get(key));
			}
			StringBuffer deptIds = new StringBuffer();
			Iterator it = departmentOrgCode.iterator();
			while(it.hasNext()){
				deptIds.append(it.next()).append(",");
			}

//			for (int j = 0; j < ids.size(); j++) {
				String realNames="";
				List<DepartmentModel> departmentModels =  remoteSecurityService.getlistDepartmentByDeptIds(toke.getToke(), toke.getProduct(), toke.getAppKey(), deptIds.toString().substring(0,deptIds.toString().length()-1));
				List<AgencyUserModel> agencyUserModels =  remoteSecurityService.listUserByUserIds(toke.getToke(), toke.getProduct(), toke.getAppKey(), planTask.getUserId());
				if(!agencyUserModels.isEmpty()){
					realNames = agencyUserModels.stream().map(AgencyUserModel::getRealName).collect(Collectors.joining(","));
					userName.append(realNames);
				}
				if(!departmentModels.isEmpty()){
					String departmentName = departmentModels.stream().map(DepartmentModel::getDepartmentName).collect(Collectors.joining(","));
					deptName.append(departmentName);
					};
//			}

		}else{
			String realNames="";
			deptId.append(planTask.getUserDept().substring(planTask.getUserDept().indexOf("@")+1)).append(",");
			deptMap.put(planTask.getUserDept().substring(0,planTask.getUserDept().indexOf("@")),planTask.getUserDept().substring(planTask.getUserDept().indexOf("@")+1));
			List<DepartmentModel> departmentModel =  remoteSecurityService.getlistDepartmentByDeptIds(toke.getToke(), toke.getProduct(), toke.getAppKey(), deptMap.get(planTask.getUserId()));
			if(departmentModel.size()>0){
				departmentModel.stream().forEach(model->{
					deptName.append(model.getDepartmentName());
				});
			}else{
				deptName.append("其他").append(",");
			}
			List<AgencyUserModel> agencyUserModels =  remoteSecurityService.listUserByUserIds(toke.getToke(), toke.getProduct(), toke.getAppKey(), planTask.getUserId());
			if(!agencyUserModels.isEmpty()){
				realNames = agencyUserModels.stream().map(AgencyUserModel::getRealName).collect(Collectors.joining(","));
//				userIds = agencyUserModels.stream().map(AgencyUserModel::getUserId).collect(Collectors.joining(","));
			}
			userName.append(realNames);
		}

        //查询部门名称
//        String depId="";
//        String depName="";
        /**
         * 对部门查询有问题需要修改

        if(iPlanDao.existsById(planTask.getPlanId())){
        	 Plan plan = iPlanDao.findById(planTask.getPlanId()).get();
        	 DepartmentModel departmentModel =  remoteSecurityService.getDepartmentByDeptId(toke.getToke(), toke.getProduct(), toke.getAppKey(), plan.getDeptId());
        	 depId = plan.getDeptId();
        	 depName = departmentModel.getDepartmentName();
        } */

		for(PlanTaskPointInputItemBo arg:planTaskPointInputItems){
			Check check = new Check();
			if (checkMap.get(arg.getPointId()) == null) {
				check.setOrgCode(arg.getOrgCode());
				check.setUserId(planTask.getUserId());
				int len = userName.toString().indexOf(",");
				if (len != -1) {
					check.setUserName(userName.toString());
				} else {
					check.setUserName(userName.toString());
				}
				check.setDepId(deptId.toString().substring(0,deptId.length()-1));
				check.setDepName(deptName.toString());
				check.setPointId(arg.getPointId());
				check.setUploadTime(new Date());
				check.setPlanId(arg.getPlanId());
				check.setPlanTaskId(arg.getPlanTaskId());
				check.setPlanTaskDetailId(arg.getPlanTaskDetailId());
				check.setRouteId(arg.getRouteId());
				check.setCheckTime(arg.getEndTime());
				check.setIsOk(CheckStatusEnum.OMISSION.getCode());
				check = iCheckDao.saveAndFlush(check);
				checkMap.put(arg.getPointId(), check);
				checkIds.add(check.getId());
			} else {
				check = checkMap.get(arg.getPointId());
			}
			if (arg.getInputItemId() != null) {
				CheckInput checkInput = new CheckInput();
				checkInput.setCheckId(check.getId());
				checkInput.setInputId(arg.getInputItemId());
				checkInput.setIsOk(CheckStatusEnum.OMISSION.getCode());
				checkInput.setRoutePointItemId(arg.getRoutePointItemId());
				checkInput.setOrderNo(arg.getOrderNo());
				checkInput.setOrgCode(arg.getOrgCode());
				checkInput.setInputName(arg.getInputName());
				checkInput.setPointClassifyId(arg.getClassifyId());
				checkInput.setPointClassifyName(arg.getClassifyName());
				iCheckInputDao.saveAndFlush(checkInput);
			}
		}

		String usrIds = planTask.getUserId();
		if (!ObjectUtils.isEmpty(usrIds)) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			String[] ids = usrIds.split(",");
			for (String userId : usrIds.split(",")) {
				Map<String,AgencyUserModel> agencyUserModelMap = remoteSecurityService.getUsersMap(toke.getToke(),toke.getProduct(),toke.getAppKey(), Collections.singleton(userIds));
				List<Map<String, String>> idOrgCodeList = new ArrayList<>();
				for(Map.Entry<String, AgencyUserModel> entry : agencyUserModelMap.entrySet()){
					String id = entry.getKey();
					AgencyUserModel agencyUserModel = entry.getValue();
					StringBuffer agencyUserOrgcode = new StringBuffer();
					agencyUserModel.getCompanys().forEach(companyModel -> {
						agencyUserOrgcode.append(companyModel.getOrgCode()).append(",");
					});
					Map<String,String> map = new HashMap<>();
					map.put(id,agencyUserOrgcode.toString().substring(0,agencyUserOrgcode.length()-1));
				}
				Map<String, String> userIdOrgCodeMap = new HashMap<>(ids.length);
				if (!CollectionUtils.isEmpty(idOrgCodeList)) {
					userIdOrgCodeMap = idOrgCodeList.stream().collect(Collectors.toMap(x-> String.valueOf(x.get(
							"id")),    x->x.get("org_code")));
				}
				if (ObjectUtils.isEmpty(userId)) {
					continue;
				}
//				planTaskMapper.reformStatistics(userId, sdf.format(new Date()), planTask.getOrgCode());
				planTaskMapper.reformStatistics(userId, sdf.format(new Date()), userIdOrgCodeMap.get(userId));

			}
		}

		// 向3d推送数据,发送消息推送
		checkIds.forEach(checkId -> {
			try {
				asyncTask.pushCheckInfoTo3D(checkId);
				asyncTask.pushCheckMessage(checkId);
			} catch (InterruptedException e) {
				log.error(e.getMessage(), e);
				e.printStackTrace();
			}
		});
		//数字换流站页面刷新
			try {
				webMqttComponent.publish(patrolTopic, "");
			}catch (Exception e){
				log.error("数字换流站页面推送失败-----------"+e.getMessage());
			}


	}

	private void removeJob(String jobName) {
		log.debug("removeJob==jobName==" + jobName);
		QuartzManager.removeJob(jobName);
	}

	private Job getJobInstance(String type) {
		switch (type) {
		case "planTask":
			return new PlanTaskJobService();
		case "task":
			return new TaskJobService();
		case "msg":
			return new MsgJobService();
		default:
			return null;
		}
	}

	@Override
	public void taskAddJob(Task task) {
		// TODO Auto-generated method stub
		long taskId = task.getId();
		if (XJConstant.TASK_WARN.equals(task.getIsWarn())) { // 设置为接受报警执行代码
			Date alarmDate = task.getWarnTime();
			addJob("task", XJConstant.MESSAGE_PUSH, taskId, alarmDate);
		}
		addJob("task", XJConstant.STATUS_MONITOR_END, taskId, task.getFinishTime());

	}

	@Override
	@Transactional
	public void taskJobPerform(long taskId, String jobType, String jobName) {
		// TODO Auto-generated method stub


		if (iTaskDao.existsById(taskId)) {
			Task task = iTaskDao.findById(taskId).get();
			Toke  toke=  remoteSecurityService.getServerToken();
			if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
				if (TaskStatusEnum.UNDERWAY.getValue() == task.getStatus()) {
					task.setStatus(TaskStatusEnum.OVERTIME.getValue());
					iTaskDao.saveAndFlush(task);
					TaskFeedback taskFeedback = new TaskFeedback();
					taskFeedback.setUserId(task.getExecutorId());
					taskFeedback.setMessage("该任务在规定时间内未完成，请核实信息！任务名称： " + task.getTitle() + " 要求完成时间：  "
							+ DateUtil.getDateFormat(task.getFinishTime(), "yyyy-MM-dd HH:mm:ss") + " 发起人："
							+ task.getPublisherName() + " 执行人：" + task.getExecutor());
					taskFeedback.setCreateDate(new Date());
					taskFeedback.setUserName(task.getExecutor());
					taskFeedback.setFeedbackTime(new Date());
					taskFeedback.setOrgCode(task.getOrgCode());
					taskFeedback.setTaskId(task.getId());
					taskFeedback.setMessageType(TaskStatusEnum.OVERTIME.getName());
					taskFeedback = taskFeedbackDao.save(taskFeedback);
					try {
						asyncTask.pushTaskDetailInfoTo3D(toke.getToke(), toke.getProduct(), toke.getAppKey(),taskId); // 超时任务向3D推送
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						log.error(e.getMessage(), e);
						e.printStackTrace();
					}
				}
			} else {
				messageService.pushTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(),task);
			}
		}
		removeJob(jobName);
	}

	@Override
	public void planTaskAddJob(PlanTask planTask) {
		// TODO Auto-generated method stub
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date endTime = sdf.parse(planTask.getEndTime());
			Date beginTime = sdf.parse(planTask.getBeginTime());
			if (PlanTaskFinishStatusEnum.OVERTIME.getValue() != planTask.getFinishStatus()) {

				// 添加状态监控定时

				int status = planTask.getFinishStatus();
				if (PlanTaskFinishStatusEnum.NOTSTARTED.getValue() == status) {
					addJob("planTask", XJConstant.STATUS_MONITOR_START, planTask.getId(), beginTime);// 添加监控任务开始时间定时任务
				}
				if (PlanTaskFinishStatusEnum.NOTSTARTED.getValue() == status
						|| PlanTaskFinishStatusEnum.UNDERWAY.getValue() == status) {
					addJob("planTask", XJConstant.STATUS_MONITOR_END, planTask.getId(), endTime);// 添加监控任务开始结束定时任务
				}

				// 查询需要推送消息提醒
				List<MsgConfigParam> configParam = msgMapper.getPlanTaskMsgConfigByUserIdAndStatus(planTask.getUserId().split(","),
						"True");
				if (!configParam.isEmpty()) {
					configParam.forEach(config -> {
						String jobType = "";
						Date time = new Date();
						int minute = Integer.valueOf(config.getValue());
						long tempTime = minute * 60 * 1000;
						if (MsgSubscribeTypeEnum.PLANWARN.getName().equals(config.getMsgType())) {
							time = new Date(beginTime.getTime() - tempTime);
							jobType = XJConstant.PLAN_TASK_WARN_MSG_PUSH + "-" + config.getUserId();
						} else if (MsgSubscribeTypeEnum.PLANBEGIN.getName().equals(config.getMsgType())) {
							time = new Date(beginTime.getTime() + tempTime);
							jobType = XJConstant.PLAN_TASK_BEGIN_MSG_PUSH + "-" + config.getUserId();
						} else if (MsgSubscribeTypeEnum.PLANEND.getName().equals(config.getMsgType())) {
							time = new Date(endTime.getTime() + tempTime);
							jobType = XJConstant.PLAN_TASK_END_MSG_PUSH + "-" + config.getUserId();
						}
						addJob("planTask", jobType, planTask.getId(), time);
					});
				}

			} else {
				updatePlanTaskStatus(planTask,PlanTaskFinishStatusEnum.OVERTIME.getValue());
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			e.printStackTrace();
		}
	}

	@Override
	@Transactional
	public void planTaskJobPerform(long planTaskId, String jobType, String jobName) {

		if (iPlanTaskDao.existsById(planTaskId)) {
			PlanTask planTask = iPlanTaskDao.findById(planTaskId).get();
			if (XJConstant.STATUS_MONITOR_START.equals(jobType)) {
				if (PlanTaskFinishStatusEnum.NOTSTARTED.getValue() == planTask.getFinishStatus()) {
					planTask.setFinishStatus(PlanTaskFinishStatusEnum.UNDERWAY.getValue());
					iPlanTaskDao.save(planTask);
				}
			} else if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
				if (PlanTaskFinishStatusEnum.UNDERWAY.getValue() == planTask.getFinishStatus()) {
					updatePlanTaskStatus(planTask, PlanTaskFinishStatusEnum.OVERTIME.getValue());
				}
			} else {
				Toke  toke=  remoteSecurityService.getServerToken();
				messageService.pushPlanTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(),planTask, jobType);
			}
		}
		removeJob(jobName);
	}

	@Override
	public void msgAddJob(Msg msg) {
		addJob("msg", XJConstant.MESSAGE_PUSH, msg.getId(), msg.getFixedTime());
	}

	@Override
	public void msgJobPerform(long msgId, String jobType, String jobName) {
		if (iMsgDao.existsById(msgId)) {
			Msg msg = iMsgDao.findById(msgId).get();
			Toke  toke=  remoteSecurityService.getServerToken();
			messageService.pushMsg(toke.getToke(), toke.getProduct(), toke.getAppKey(),msg);
		}
		removeJob(jobName);
	}

}
