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

import com.utic.center.common.utils.LogUtils;
import com.utic.center.common.utils.TimeUtils;
import com.utic.center.utic.stat.server.dto.BatchJobInfoDto;
import com.utic.center.utic.stat.server.repository.ApplicationRepository;
import com.utic.center.utic.stat.server.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;

import java.time.LocalDateTime;

@Slf4j
@Controller
@RequiredArgsConstructor
public class UticStatServerController {

    private final UticStatPrepareService prepareService;
    private final UticStat04MinEtlpService etlp04MinService;
    private final UticStat05MinFltrService fltr05MinService;
    private final UticStat05MinStatService stat05MinService;
    private final UticStat15MinStatService stat15MinService;
    private final UticStatPatternService patternService;

    private long etlpElapsed = 0;
    private long dayElapsed = 0;
    private String prevPrcsTime = "";
    private boolean isRunning = false;

    private boolean isEtlp = false;
    private boolean is05Min = false;
    private boolean is15Min = false;
    private boolean is30Min = false;
    private boolean isHour = false;
    private boolean isDay = false;

    private void calculateTime() {
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();       // 현재 시
        int minute = now.getMinute();   // 현재 분

        this.isEtlp = ((minute + 1) % 5 == 0);      // 4분마다 ETLP 실행
        this.is05Min = (minute % 5 == 0);           // 5분마다 실행
        this.is15Min = (minute % 15 == 0);          // 15분마다 실행
        this.is30Min = (minute % 30 == 0);          // 30분마다 실행
        this.isHour = (minute == 0);                // 매시 정각마다 실행
        this.isDay = (hour == 0 && minute == 0);    // 매일 자정마다 실행
    }

    private void initialize() {
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();
        int hour = now.getHour();
        int minute = now.getMinute();
        String prcsTime = String.format("%04d%02d%02d%02d%02d00", year, month, day, hour, minute);

        ApplicationRepository.past10Min = TimeUtils.addMinutes(prcsTime, -10);
        ApplicationRepository.past25Min = TimeUtils.addMinutes(prcsTime, -25);
        ApplicationRepository.past30Min = TimeUtils.addMinutes(prcsTime, -30);
        ApplicationRepository.past45Min = TimeUtils.addMinutes(prcsTime, -45);
        ApplicationRepository.past60Min = TimeUtils.addMinutes(prcsTime, -60);
        ApplicationRepository.past90Min = TimeUtils.addMinutes(prcsTime, -90);
        ApplicationRepository.past120Min = TimeUtils.addMinutes(prcsTime, -120);
        ApplicationRepository.regDate = ApplicationRepository.past25Min;

    }

    public void run() {
        final String header = "==========================================================================================================";
        final String step = "----------------------------------------------------------------------------------------------------------";
        final String completed = "**********************************************************************************************************";
        final long start = System.currentTimeMillis();
        long tmpStart;
        calculateTime();

        if (this.isEtlp) {
            // 4분마다 실행
            this.isRunning = true;
            this.etlp04MinService.processing();
            this.prepareService.processing();
            this.isRunning = false;
            this.etlpElapsed = System.currentTimeMillis() - start;
            return;
        }

        if (!this.is05Min) { // 5분마다 실행
            return;
        }

        log.info(header);
        if (this.isRunning) {
            log.warn("[WAN] {}: [{}] - Already running.", LogUtils.elapsedLog("Overlapping"), this.prevPrcsTime);
        }

        this.isRunning = true; // 현재 작업이 실행중임을 표시
        this.prevPrcsTime = TimeUtils.getCurrentTimeString(); // 현재 작업 시간 저장

        log.info("##>> 05MIN {}: [{}]", LogUtils.elapsedLogLength("정주기 교통정보 통계 Start", 5), this.prevPrcsTime);

        BatchJobInfoDto jobInfo = new BatchJobInfoDto(TimeUtils.now());

        jobInfo.setEtlp04MinTime(this.etlpElapsed);
        jobInfo.setStat01MonthTime(this.dayElapsed);

        try {
            // 0. 초기화 작업
            initialize();

            // 1. 05분 통계작업 실행
            // 1-1. FILTERING 작업 실행
            tmpStart = System.currentTimeMillis();
            this.fltr05MinService.processing();
            jobInfo.setFltr05MinTime(System.currentTimeMillis() - tmpStart);
            log.info(step);

            // 1-2. 05분 통계작업 실행
            tmpStart = System.currentTimeMillis();
            this.stat05MinService.processing();
            jobInfo.setStat05MinTime(System.currentTimeMillis() - tmpStart);
            log.info(step);

            if (this.is15Min) {
                // 2. 15분 통계작업 실행
                tmpStart = System.currentTimeMillis();
                this.stat15MinService.processing();
                jobInfo.setStat15MinTime(System.currentTimeMillis() - tmpStart);
                log.info(step);
            }
            if (this.is30Min) {
                // 3. 30분 통계작업 실행(연계하지 않음, 2025-09-08)
//                tmpStart = System.currentTimeMillis();
//                this.stat30MinService.processing();
//                jobInfo.setStat30MinTime(System.currentTimeMillis() - tmpStart);
//                log.info(step);
            }
            if (this.isHour) {
                // 4. 1시간 통계작업 실행(연계하지 않음, 2025-09-08)
//                tmpStart = System.currentTimeMillis();
//                this.stat01HourService.processing();
//                jobInfo.setStat01HourTime(System.currentTimeMillis() - tmpStart);
//                log.info(step);

                // 5. 1일 통계작업 실행(1시간 통계 작업 후에 1일 통계작업을 점진적으로 생성)(연계하지 않음, 2025-09-08)
//                tmpStart = System.currentTimeMillis();
//                this.stat01DayService.processing();
//                jobInfo.setStat01DayTime(System.currentTimeMillis() - tmpStart);
//                log.info(step);

                // 6. 패턴 초기화 작업(매 1시간 주기로 실행함)
                tmpStart = System.currentTimeMillis();
                this.patternService.processing();
                jobInfo.setPtrnInitTime(System.currentTimeMillis() - tmpStart);
                log.info(step);

            }
            if (this.isDay) {
                // 7. 월 통계작업 실행(연계하지 않음, 2025-09-08)
//                tmpStart = System.currentTimeMillis();
//                this.stat01MonthService.processing();
//                this.dayElapsed = System.currentTimeMillis() - tmpStart;
//                jobInfo.setStat01MonthTime(this.dayElapsed);
//                log.info(step);
            }
        }
        finally {
            this.isRunning = false; // 현재 작업이 종료됨을 표시
        }

        // 작업 정보를 리스트에 저장(http://localhost:9871/info)
        long executionTime = System.currentTimeMillis() - start;
        jobInfo.setEndTime(TimeUtils.now());
        jobInfo.setElapsedTime(executionTime);
        ApplicationRepository.addJobInfo(jobInfo);

        log.info("<<## 05MIN {} [{}].", LogUtils.elapsedLogLength("정주기 교통정보 통계 End", executionTime, 5), this.prevPrcsTime);
        log.info(completed);
    }
}
