package com.spring.infra.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.springframework.stereotype.Service;

import com.spring.infra.batch.BatchJobInfoData;
import com.spring.infra.batch.BatchJobInfoService;

import lombok.RequiredArgsConstructor;

/**
 * Quartz 스케줄러를 관리하는 서비스 클래스입니다.
 * 
 * <p>이 클래스는 Quartz 스케줄러의 작업을 생성, 삭제 및 관리하는 기능을 제공합니다.</p>
 * 
 * <p>주요 기능:</p>
 * <ul>
 *   <li>작업 및 트리거 생성</li>
 *   <li>작업 삭제 및 스케줄러 초기화</li>
 *   <li>작업 상태 관리</li>
 * </ul>
 * 
 * @author mindol
 * @version 1.0
 */
@Service
@RequiredArgsConstructor
public class QuartzScheduleService {
    
    /**
     * Quartz 스케줄러 객체입니다.
     * 
     * <p>스케줄러의 작업을 관리하는 데 사용됩니다.</p>
     */
    private final Scheduler scheduler;
    private final BatchJobInfoService batchJobInfoService;

    /**
     * 모든 작업을 삭제합니다.
     * 
     * <p>스케줄러에 등록된 모든 작업을 삭제하고 초기화합니다.</p>
     * 
     * @throws IllegalStateException 작업 삭제 중 오류가 발생한 경우
     */
    public void clearJobs() {
        try {
            scheduler.clear();
        } catch (SchedulerException e) {
            throw new IllegalStateException("Failed to clear jobs from scheduler", e);
        }
    }

    /**
     * 새로운 작업 트리거를 생성합니다.
     * 
     * <p>주어진 배치 작업 이름을 기반으로 작업과 트리거를 생성하고 스케줄러에 등록합니다.</p>
     * 
     * @param beanName 배치 작업의 이름
     * @throws IllegalStateException 작업 스케줄링 중 오류가 발생한 경우
     */
    public void createJobTrigger(String beanName) {
        BatchJobInfoData batchJobInfoData = batchJobInfoService.getBatchJobInfo(beanName);

        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("jobName", batchJobInfoData.getJobName());

        JobDetail jobDetail = JobBuilder.newJob(QuartzJobLauncher.class)
                .withIdentity(batchJobInfoData.getJobName(), batchJobInfoData.getJobGroup())
                .setJobData(jobDataMap)
                .storeDurably(true)
                .withDescription(batchJobInfoData.getDescription())
                .build();

        CronTrigger trigger = TriggerBuilder.newTrigger()
                .forJob(jobDetail)
                .withIdentity(batchJobInfoData.getJobName() + "Trigger", batchJobInfoData.getJobGroup())
                .withSchedule(CronScheduleBuilder.cronSchedule(batchJobInfoData.getCronExpression()))
                .withDescription(batchJobInfoData.getDescription())
                .build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new IllegalStateException("Error scheduling Quartz job: " + batchJobInfoData.getJobName(), e);
        }
    }

}
