package com.eactive.eai.rms.common.scheduler;

import com.eactive.eai.rms.common.base.BaseAnnotationController;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.common.scheduler.ui.JobInfoUI;
import com.eactive.eai.rms.common.scheduler.ui.SchedulerUISearch;
import com.eactive.eai.rms.common.util.MonitoringSyncAgent;
import com.eactive.eai.rms.common.vo.GridResponse;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class SchedulerManController extends BaseAnnotationController {

   @Autowired
   private Scheduler scheduler;

   @Autowired @Qualifier("clusteredScheduler")
   private Scheduler clusteredScheduler;

	@Autowired
	private SchedulerManService service;

	@Autowired
	private ComboService comboService;

	@Autowired
	@Qualifier("monitoringSyncAgent")
	private MonitoringSyncAgent monitoringSyncAgent;

	@Autowired
	private EMSScheduler emsScheduler;

	@GetMapping(value = "/common/scheduler/schedulerMan.view")
	public String viewList() {
		return "/common/scheduler/schedulerMan";
	}

	@GetMapping(value = "/common/scheduler/schedulerMan.view", params = "cmd=DETAIL")
	public String viewDetail() {
		return "/common/scheduler/schedulerManDetail";
	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=LIST_INIT_COMBO")
	public ResponseEntity<Map<String, Object>> initCombo() {

		List<ComboVo> instanceList = comboService.getFromMonitoringCode("EMS_INSTANCE_NAME", "Y");

		// USE_YN_TYPE 조회
		List<ComboVo> listUseYnType = comboService.getFromCode("USE_YN_TYPE");

		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("instanceList", instanceList);
		resultMap.put("useYnTypeRows", listUseYnType);

		return ResponseEntity.ok(resultMap);
	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=LIST")
	public ResponseEntity<GridResponse<JobInfoUI>> selectList(@PageableDefault(sort = "id") Pageable pageable,
                                               SchedulerUISearch schedulerUISearch) {
		Page<JobInfoUI> page = service.selectList(pageable, schedulerUISearch);
		return ResponseEntity.ok(new GridResponse<>(page));

	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=DETAIL")
	public ResponseEntity<JobInfoUI> selectDetail(String jobName) {
		JobInfoUI jobInfoUI = service.selectDetail(jobName);
		return ResponseEntity.ok(jobInfoUI);
	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=INSERT")
	public ResponseEntity<Void> insert(JobInfoUI jobInfoUI) {

		service.insert(jobInfoUI);
		syncReloadScheduler(jobInfoUI.getId());

		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=UPDATE")
	public ResponseEntity<Void> update(JobInfoUI jobInfoUI) {
		service.update(jobInfoUI);
		try {
			emsScheduler.reloadJob(jobInfoUI.getId());
		} catch (Exception e) {
			logger.error("reloadJob error on current server", e);
		}
		syncReloadScheduler(jobInfoUI.getId());
		return ResponseEntity.ok().build();
	}

	@PostMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=DELETE")
	public ResponseEntity<Void> delete(String jobName) {
		service.delete(jobName);
		syncReloadScheduler(jobName);
		return ResponseEntity.ok().build();
	}

	public void syncReloadScheduler(String jobName) {

		Map<String, String> paramMap = new HashMap<>();
		Map<String, String> ret = null;
		paramMap.put("jobName", jobName);
		String url = "/monitoring/schedulerReload.do";

		try {
			ret = monitoringSyncAgent.targetSync(url, paramMap);
		} catch (Exception e) {
			logger.error("syncReloadScheduler error", e);
		} finally {
			logger.info("Scheduler Sync Result : " + ret);
		}
	}

   @RequestMapping(value = "/common/scheduler/schedulerMan.json", params = "cmd=TRANSACTION_RUN")
   private @ResponseBody ResponseEntity<String> runSchedule(String jobName) {

      boolean onMemorySchedulerJob = false;
      boolean clusteredSchedulerJob = false;

      try {

         onMemorySchedulerJob = scheduler.getJobDetail(new JobKey(jobName, Scheduler.DEFAULT_GROUP)) != null;
         clusteredSchedulerJob = clusteredScheduler.getJobDetail(new JobKey(jobName, Scheduler.DEFAULT_GROUP)) != null;

         if (!onMemorySchedulerJob && !clusteredSchedulerJob) {
            return ResponseEntity.internalServerError().body("등록된 스케줄이 없어 기동에 실패했습니다.");
         }

      } catch (SchedulerException e) {
         logger.error(e);
         return ResponseEntity.internalServerError().body("등록 스케줄 조회중 오류가 발생하였습니다.");
      }

      try {
         if (onMemorySchedulerJob) {
            scheduler.triggerJob(new JobKey(jobName, Scheduler.DEFAULT_GROUP));
         } else if (clusteredSchedulerJob) {
            clusteredScheduler.triggerJob(new JobKey(jobName, Scheduler.DEFAULT_GROUP));
         }

      } catch (SchedulerException e) {
         logger.error(e);
         return ResponseEntity.internalServerError().body(jobName + " 기동 중 오류 발생하였습니다. 자세한 내용은 로그를 확인해주세요.");
      }

      return ResponseEntity.ok("run schedule " + jobName + " immediately.");

   }

}
