package com.spring.infra.quartz;

import javax.sql.DataSource;

import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import lombok.RequiredArgsConstructor;

/**
 * Quartz 스케줄러 설정을 위한 구성 클래스입니다.
 * 
 * <p>이 클래스는 Quartz 스케줄러의 기본 설정을 제공하며, 다음과 같은 기능을 수행합니다:</p>
 * <ul>
 *   <li>JobFactory 빈 생성 및 설정</li>
 *   <li>SchedulerFactoryBean 생성 및 설정</li>
 *   <li>Quartz 작업에 대한 의존성 주입 지원</li>
 * </ul>
 * 
 * @author mindol
 * @version 1.0
 */
@Configuration
@RequiredArgsConstructor
public class QuartzConfig {
    
    private final QuartzProperties quartzProperties;
    private final DataSource dataSource;
    private final PlatformTransactionManager transactionManager;

    /**
     * Quartz Schedule Job에 의존성을 주입하기 위한 JobFactory를 생성합니다.
     * 
     * <p>이 메소드는 Spring의 AutowireCapableBeanFactory를 사용하여
     * Quartz Job 인스턴스에 자동으로 의존성을 주입합니다.</p>
     * 
     * @param beanFactory Spring의 AutowireCapableBeanFactory
     * @return 생성된 JobFactory 인스턴스
     */
    @Bean
    JobFactory jobFactory(AutowireCapableBeanFactory beanFactory) {
        return (TriggerFiredBundle bundle, Scheduler scheduler) -> {
            Job job = beanFactory.createBean(bundle.getJobDetail().getJobClass());
            beanFactory.autowireBean(job);
            return job;
        };
    }
    
    /**
     * Quartz Scheduler를 생성하고 설정하는 SchedulerFactoryBean을 구성합니다.
     * 
     * <p>이 메소드는 다음과 같은 설정을 수행합니다:</p>
     * <ul>
     *   <li>스케줄러 이름 설정</li>
     *   <li>Quartz 속성 설정</li>
     *   <li>데이터 소스 및 트랜잭션 매니저 설정</li>
     *   <li>JobFactory 설정</li>
     *   <li>자동 시작 및 종료 시 작업 완료 대기 설정</li>
     * </ul>
     *
     * @param jobFactory 사용할 JobFactory 인스턴스
     * @return 구성된 SchedulerFactoryBean 인스턴스
     */
    @Bean
    SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
        var factory = new SchedulerFactoryBean();
        factory.setSchedulerName("SampleProject-0.0.1");
        factory.setQuartzProperties(quartzProperties.toProperties());
        factory.setOverwriteExistingJobs(true);
        factory.setDataSource(dataSource);
        factory.setTransactionManager(transactionManager);
        factory.setJobFactory(jobFactory);
        factory.setAutoStartup(true);
        factory.setWaitForJobsToCompleteOnShutdown(true);
        return factory;
    }

}
