package kr.xit.core.biz.batch.task;

import kr.xit.core.biz.batch.model.BatchCmmDTO.BatchLock;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import kr.xit.core.support.utils.Checks;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

/**
 * <pre>
 * description : 배치 시작시 lock table insert or update
 *               시작하는 배치 인스턴스의 사용여부(use_yn)를 사용(Y)으로 변경(생성)
 *               -> 사용여부가 사용(Y) 이면 실행중 이므로 배치 종료
 *
 * packageName : kr.xit.core.biz.batch.task
 * fileName    : BatchStartTasklet
 * author      : limju
 * date        : 2023-05-16
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-05-16    limju       최초 생성
 * 2023-08-21    limju       lock이 걸린 경우 release 하도록 변경 : 중복실행 되지 않도록 배치 시간 보장 전제
 * </pre>
 * @see kr.xit.core.aop.TraceLoggerAspect
 */
@Slf4j
public class BatchStartTasklet implements Tasklet {
    private final IBatchCmmService batchCmmService;

    public BatchStartTasklet(IBatchCmmService batchCmmService) {
        this.batchCmmService = batchCmmService;
    }

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        String jobName = contribution.getStepExecution().getJobExecution().getJobInstance().getJobName();
        BatchLock dto = batchCmmService.findById(jobName)
            .orElseGet(()-> BatchLock
                    .builder()
                    .build());

        if(Checks.isEmpty(dto.getInstanceId())){
            dto.setInstanceId(jobName);
            dto.setResult(null);
            dto.setUseYn("Y");
            batchCmmService.addBatchLock(dto);
            batchCmmService.addBatchLog(dto);
            MDC.put("batch_log_id", dto.getBatchLogId());
        }else{
            if("Y".equals(dto.getUseYn())){
                log.error("======= [{}] 배치 실행(사용) 중으로 종료 =======", jobName);
                contribution.setExitStatus(ExitStatus.FAILED);
                dto.setResult("배치 실행(사용) 중으로 종료");
                // lock이 걸린 경우 reset : 2023-08-21
                dto.setUseYn("N");
                batchCmmService.modifyBatchLock(dto);
                batchCmmService.addBatchLog(dto);
            }else{
                dto.setUseYn("Y");
                dto.setResult(null);
                batchCmmService.modifyBatchLock(dto);
                batchCmmService.addBatchLog(dto);
                MDC.put("batch_log_id", dto.getBatchLogId());
            }
        }
        return RepeatStatus.FINISHED;
    }
}
