package com.tsi.comm.server.scheduler;

import com.tsi.app.common.utils.Elapsed;
import com.tsi.app.common.utils.TimeUtils;
import com.tsi.comm.server.kafka.KafkaConsumerService;
import com.tsi.comm.server.kafka.KafkaProducerService;
import com.tsi.comm.server.mybatis.TsiDatabaseService;
import com.tsi.comm.server.repository.TsiAlarmManager;
import com.tsi.comm.server.repository.TsiNodeManager;
import com.tsi.comm.server.repository.TsiSessionManager;
import com.tsi.comm.server.repository.TsiTpmsManager;
import com.tsi.comm.server.vo.TsiAlarmConfigVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

@Slf4j
@EnableScheduling
@Component
public class TsiCommScheduler {

    private final TsiDatabaseService tsiDatabaseService;
    private final KafkaProducerService kafkaProducerService;
    private final KafkaConsumerService kafkaConsumerService;

    public TsiCommScheduler(TsiDatabaseService tsiDatabaseService, KafkaProducerService kafkaProducerService, KafkaConsumerService kafkaConsumerService) {
        this.tsiDatabaseService = tsiDatabaseService;
        this.kafkaProducerService = kafkaProducerService;
        this.kafkaConsumerService = kafkaConsumerService;
    }

    @PreDestroy
    public void onShutDown() {
    }

    @Async
    @Scheduled(cron = "* * * * * *")  // 1초 주기 작업 실행
    public void staticsForPacketSecond() {
        Elapsed elapsed = new Elapsed();
        TsiTpmsManager.getInstance().resetSecond();
        log.info("{}", String.format("%25s: %s", "staticsForPacketSecond", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0/5 * * * * *")  // 5초 주기 작업 실행
    public void checkKafkaServerAlive() {
        Elapsed elapsed = new Elapsed();
        this.kafkaConsumerService.start();
        this.kafkaProducerService.sendPing();
        log.info("{}", String.format("%25s: %s", "checkKafkaServerAlive", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0/5 * * * * *")  // 5초 주기 작업 실행
    public void checkSessionTimeout() {
        if (!TsiAlarmManager.getInstance().checkAlarm(TsiAlarmConfigVo.COMM_02)) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        long timeout = 0;
        TsiAlarmConfigVo vo = TsiAlarmManager.getInstance().get(TsiAlarmConfigVo.COMM_02);
        if (vo == null) return; // 이거면 안됌.
        timeout = vo.getValue() * 1000;
        if (timeout <= 0) {
            log.error("checkSessionTimeout: timeout value error: {}", timeout);
            return;
        }
        TsiNodeManager.getInstance().checkSessionTimeout(timeout);
        log.info("{}", String.format("%25s: %s", "checkSessionTimeout", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0/10 * * * * *")  // 10초 주기 작업 실행
    public void reportNodeSessionAlive() {
        Elapsed elapsed = new Elapsed();
        TsiNodeManager.getInstance().reportNodeSessions();
        TsiSessionManager.getInstance().reportChannelSessions();
        log.info("{}", String.format("%25s: %s", "reportNodeSessionAlive", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0 * * * * *")  // 1분 주기 작업 실행
    public void staticsForPacketMinute() {
        Elapsed elapsed = new Elapsed();
        TsiTpmsManager.getInstance().resetMinute();
        log.info("{}", String.format("%25s: %s", "staticsForPacketMinute", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0 0 0 * * *")  // 1일 주기 작업 실행
    public void staticsForPacketDay() {
        Elapsed elapsed = new Elapsed();
        TsiTpmsManager.getInstance().resetDay();
        log.info("{}", String.format("%25s: %s", "staticsForPacketDay", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

    @Async
    @Scheduled(cron = "0 * * * * *")  // 1분 주기 작업 실행
    public void loadBaseDatabase() {
        Elapsed elapsed = new Elapsed();
        this.tsiDatabaseService.loadDatabase();
        this.tsiDatabaseService.updateProcessState(1);
        log.info("{}", String.format("%25s: %s", "loadBaseDatabase", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
    }

}
