package com.utic.center.utic.stat.server.scheduler;

import com.utic.center.common.utils.TimeUtils;
import com.utic.center.utic.stat.server.config.ApplicationConfig;
import com.utic.center.utic.stat.server.controller.UticStatServerController;
import com.utic.center.utic.stat.server.health.SystemHealthService;
import com.utic.center.utic.stat.server.service.ProcessStateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
@RequiredArgsConstructor
@EnableScheduling
@Component
public class ApplicationScheduler {

    private final ApplicationConfig config;
    private final ProcessStateService processStateService;
    private final UticStatServerController controller;
    private final SystemHealthService healthService;

    private final AtomicBoolean isScheduleRunning = new AtomicBoolean(false);

    private String scheduleTime;

    @Scheduled(cron = "0 * * * * *")
    public void scheduleProcess() {
        if (!this.config.isStartSchedule()) {
            return;
        }

        if (!this.healthService.checkSystemHealth()) {
            // 시스템이 과부하이면 처리하지 않는다.
            return;
        }

        // 이전 작업이 아직 실행 중이면 스킵(비동기 처리로 변경할 경우 대비-보혐)
        if (!this.isScheduleRunning.compareAndSet(false, true)) {
            log.warn("ApplicationScheduler.scheduleProcess: Previous Schedule Running. {}, {}", this.scheduleTime, TimeUtils.getCurrentTimeString());
            return;
        }

        this.scheduleTime = TimeUtils.getCurrentTimeString();

        try {
            this.controller.run();
            this.processStateService.processRunning();
        } catch (Exception e) {
            log.error("ApplicationScheduler.scheduleProcess: Exception {}", e.getMessage());
        }
        finally {
            this.isScheduleRunning.set(false); // 작업 완료 후 플래그 초기화
        }
    }

}
