package com.iqser.red.service.persistence.management.v1.processor.lifecycle;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.ApplicationListener;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@RequiredArgsConstructor
public class LifecycleManager implements SmartLifecycle, ApplicationListener<ContextClosedEvent> {

    private volatile boolean running; // by default initialized as false
    private volatile boolean shutdownInitiated; // by default initialized as false
    private final Object shutdownMonitor = new Object();
    private final AtomicInteger activeTasks = new AtomicInteger(0);
    private final CountDownLatch latch = new CountDownLatch(1);


    public void countDown() {

        latch.countDown();
    }


    public int incrementAndGet() {

        return activeTasks.incrementAndGet();
    }


    public int decrementAndGet() {

        return activeTasks.decrementAndGet();
    }


    @Override
    public void start() {

        synchronized (shutdownMonitor) {
            running = true;
        }
    }


    @Override
    public void stop() {

        synchronized (shutdownMonitor) {
            running = false;
            if (activeTasks.get() == 0) {
                latch.countDown(); // No active tasks, release the latch immediately
            }
        }
    }


    @Override
    public boolean isRunning() {

        return running;
    }


    @Override
    public boolean isAutoStartup() {

        return true;
    }


    @Override
    public int getPhase() {

        return Integer.MAX_VALUE; // Start this component last and stop it first
    }


    @Override
    public void onApplicationEvent(ContextClosedEvent event) {

        synchronized (shutdownMonitor) {
            if (shutdownInitiated) {
                return; // Avoid multiple shutdown initiations
            }
            shutdownInitiated = true;
        }

        stop();
        log.info("Context is closing, waiting for ongoing tasks to complete.");
        try {
            latch.await(); // Wait for the latch to count down to zero
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Shutdown was interrupted", e);
        }
    }

}
