package kr.xit.batch.ens.job;

import kr.xit.batch.ens.task.SndngSendBulksTasklet;
import kr.xit.biz.ens.service.IEnsBatchSendService;
import kr.xit.core.biz.batch.CustomRunIdIncrementer;
import kr.xit.core.biz.batch.listener.CustomJobListener;
import kr.xit.core.biz.batch.listener.CustomStepListener;
import kr.xit.core.biz.batch.listener.NoWorkFoundStepListener;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import kr.xit.core.biz.batch.task.BatchEndTasklet;
import kr.xit.core.biz.batch.task.BatchFailEndTasklet;
import kr.xit.core.biz.batch.task.BatchStartTasklet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * <pre>
 * description : 문자 발송 시스템 연계 - 전송
 *
 * packageName : kr.xit.batch.ens.job
 * fileName    : SndngSnedBulksJobConfig
 * author      : limju
 * date        : 2023-06-12
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-06-12    limju       최초 생성
 *
 * </pre>
 */
@Slf4j
@RequiredArgsConstructor
@Configuration
public class SndngSnedBulksJobConfig {
    private static final String JOB_NAME = "SndngSendBulksJob";

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    private final IBatchCmmService lockService;
    private final IEnsBatchSendService sendService;

    @Bean(name = JOB_NAME)
    public Job sndngSendBulksJob() {
        return jobBuilderFactory.get(JOB_NAME)
            .incrementer(new CustomRunIdIncrementer())
            .listener(new CustomJobListener())
            .listener(new CustomStepListener())
            .listener(new NoWorkFoundStepListener())

            // JOB 시작
            // start() 결과가 FAILED 인경우 종료
            .start(start())
            .on("FAILED")
            .end()

            // start()의 결과로 부터 FAILED를 제외한 모든 경우 to() 실행
            //.from(start())
            .on("*")
            .to(execution())
            .on("FAILED")
            .to(fail())

            .from(execution())
            // to() 실행 결과와 상관 없이 end() 실행
            .on("*")
            .to(end())

            // JOB 종료
            .end()

            .build();
    }

    @Bean(name = JOB_NAME + "_step")
    public Step execution() {
        return stepBuilderFactory.get(JOB_NAME + "_step")
            .tasklet(new SndngSendBulksTasklet(sendService))
            .build();
    }

    @JobScope
    @Bean(name = JOB_NAME + "_start_step")
    protected Step start() {
        return stepBuilderFactory.get("Job_Locking")
            .tasklet(new BatchStartTasklet(lockService))
            .build();
    }

    @JobScope
    @Bean(name = JOB_NAME + "_end_step")
    protected Step end() {
        return stepBuilderFactory.get("Lock_Release")
            .tasklet(new BatchEndTasklet(lockService))
            .build();
    }

    @JobScope
    @Bean(name = JOB_NAME + "_fail_step")
    protected Step fail() {
        return stepBuilderFactory.get("Lock_Release")
            .tasklet(new BatchFailEndTasklet(lockService))
            .build();
    }
}
