package vassistent.bootstrap;

import vassistent.service.MqttClientService;
import vassistent.service.ProcessManagerService;
import vassistent.util.Logger;

import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Coordinates graceful shutdown of MQTT, managed external processes, and runtime artifacts.
 */
public class ApplicationShutdownManager {

    private static final String RUNTIME_DB_FILE = "data/health.db";

    private final ApplicationContext context;
    private final AtomicBoolean shutdownStarted = new AtomicBoolean(false);
    private final AtomicBoolean shutdownHookRegistered = new AtomicBoolean(false);

    /**
     * Creates a shutdown manager for the provided application context.
     *
     * @param context initialized application context
     */
    public ApplicationShutdownManager(ApplicationContext context) {
        this.context = context;
    }

    /**
     * Registers the JVM shutdown hook once for this manager instance.
     */
    public void registerJvmShutdownHook() {
        if (!shutdownHookRegistered.compareAndSet(false, true)) {
            return;
        }

        Runtime.getRuntime().addShutdownHook(
                new Thread(this::shutdown)
        );
    }

    /**
     * Executes shutdown steps for managed integrations.
     */
    public void shutdown() {
        if (!shutdownStarted.compareAndSet(false, true)) {
            return;
        }

        Logger.info("SHUTDOWN", "Shutdown sequencing started");

        disconnectMqtt();
        stopExternalProcesses();
        deleteRuntimeDatabase();

        Logger.info("SHUTDOWN", "Shutdown sequencing finished");
        Logger.shutdown();
    }

    /**
     * Disconnects from MQTT if a client service is available.
     */
    private void disconnectMqtt() {

        try {
            MqttClientService mqtt = context.getMqttService();

            if (mqtt != null) {
                mqtt.disconnect();
            }

            Logger.info("SHUTDOWN", "MQTT disconnected");
        } catch (Exception e) {
            Logger.error("SHUTDOWN", "MQTT shutdown failed", e);
        }
    }

    /**
     * Stops all external processes that were launched by the process manager.
     */
    private void stopExternalProcesses() {

        try {

            ProcessManagerService pm = context.getProcessManagerService();

            if (pm != null) {
                pm.shutdown();
            }

            Logger.info("SHUTDOWN", "External processes stopped");

        } catch (Exception e) {
            Logger.error("SHUTDOWN", "Process shutdown failed", e);
        }
    }

    /**
     * Deletes the runtime SQLite database file when present.
     */
    private void deleteRuntimeDatabase() {

        try {

            File dbFile = new File(RUNTIME_DB_FILE);

            if (!dbFile.exists()) {
                return;
            }

            boolean deleted = dbFile.delete();

            if (deleted) {
                Logger.info("SHUTDOWN", "Runtime database deleted");
            } else {
                Logger.warn("SHUTDOWN", "Runtime database could not be deleted");
            }

        } catch (Exception e) {
            Logger.error("SHUTDOWN", "Runtime database deletion failed", e);
        }
    }
}
