package gc.mda.signal_batch.batch.job;

import gc.mda.signal_batch.batch.listener.JobCompletionListener;
import gc.mda.signal_batch.global.websocket.service.DailyTrackCacheManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.JobParametersValidator;
import org.springframework.batch.core.job.DefaultJobParametersValidator;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Slf4j
@Configuration
@Profile("!query")  // query 프로파일에서는 배치 작업 비활성화
@RequiredArgsConstructor
@ConditionalOnProperty(name = "vessel.batch.scheduler.enabled", havingValue = "true", matchIfMissing = true)
public class DailyAggregationJobConfig {

    private final JobRepository jobRepository;
    private final DailyAggregationStepConfig dailyAggregationStepConfig;
    private final JobCompletionListener jobCompletionListener;
    private final DailyTrackCacheManager dailyTrackCacheManager;

    @Bean
    public Job dailyAggregationJob() {
        return new JobBuilder("dailyAggregationJob", jobRepository)
                .incrementer(new RunIdIncrementer())
                .validator(dailyJobParametersValidator())
                .listener(jobCompletionListener)
                .listener(dailyCacheRefreshListener())
                .start(dailyAggregationStepConfig.mergeDailyTracksStep())
                .next(dailyAggregationStepConfig.gridDailySummaryStep())
                .next(dailyAggregationStepConfig.areaDailySummaryStep())
                .build();
    }

    @Bean
    public JobExecutionListener dailyCacheRefreshListener() {
        return new JobExecutionListener() {
            @Override
            public void beforeJob(JobExecution jobExecution) {
                // no-op
            }

            @Override
            public void afterJob(JobExecution jobExecution) {
                if (jobExecution.getStatus().isUnsuccessful()) {
                    log.warn("Daily aggregation job failed, skipping cache refresh");
                    return;
                }
                try {
                    log.info("Daily aggregation job completed, refreshing daily track cache");
                    dailyTrackCacheManager.refreshAfterDailyJob();
                } catch (Exception e) {
                    log.error("Failed to refresh daily track cache after job: {}", e.getMessage());
                }
            }
        };
    }
    
    @Bean
    public JobParametersValidator dailyJobParametersValidator() {
        DefaultJobParametersValidator validator = new DefaultJobParametersValidator();
        validator.setRequiredKeys(new String[]{"startTime", "endTime", "timeBucket"});
        validator.setOptionalKeys(new String[]{"executionTime", "enableAbnormalDetection"});
        return validator;
    }
}