package com.spring.infra.quartz;

import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.lang.NonNull;
import org.springframework.scheduling.quartz.QuartzJobBean;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Quartz 작업을 실행하는 Spring Batch Job 실행기 클래스입니다.
 * 
 * <p>이 클래스는 Quartz 스케줄러에 의해 호출되며, 지정된 Spring Batch Job을 실행합니다.</p>
 * 
 * <p>주요 기능:</p>
 * <ul>
 *   <li>JobRegistry에서 지정된 이름의 Job을 조회</li>
 *   <li>Job 실행을 위한 JobParameters 생성</li>
 *   <li>JobLauncher를 통한 Job 실행</li>
 * </ul>
 * 
 * @author mindol
 * @version 1.0
 * @see QuartzJobBean
 * @see JobLauncher
 * @see JobRegistry
 */
@Slf4j
@RequiredArgsConstructor
public class QuartzJobLauncher extends QuartzJobBean {

    private static final String JOB_PARAMETERS_INSTANCE_KEY = "InstanceId";
    private static final String JOB_PARAMETERS_TIMESTAMP_KEY = "timestamp";
    
    private final JobLauncher jobLauncher;
    private final JobRegistry jobRegistry;

    /**
     * Quartz 스케줄러에 의해 호출되는 메소드로, 실제 Job을 실행합니다.
     * 
     * <p>이 메소드는 다음과 같은 작업을 수행합니다:</p>
     * <ol>
     *   <li>JobRegistry에서 지정된 이름의 Job을 조회</li>
     *   <li>현재 시간을 기반으로 한 고유한 JobParameters 생성</li>
     *   <li>JobLauncher를 사용하여 Job 실행</li>
     * </ol>
     * 
     * @param context Quartz JobExecutionContext 객체
     */
    @Override
    protected void executeInternal(@NonNull JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String jobName = jobDataMap.getString("jobName");

        try {
            Job job = jobRegistry.getJob(jobName);
            JobParameters params = new JobParametersBuilder()
                .addString(JOB_PARAMETERS_INSTANCE_KEY, context.getScheduler().getSchedulerInstanceId())
                .addLong(JOB_PARAMETERS_TIMESTAMP_KEY, System.currentTimeMillis())
                .toJobParameters();
            jobLauncher.run(job, params);
        } catch (Exception e) {
            log.error("Job execution exception! - {}", e.getMessage(), e);
            throw new JobExecutionException();
        }
    }

}
