import { loggerProvider } from '../../utils/logging/logger-provider.js';
const DEFAULT_TIMEOUT_MS = 5000;
const ENV_SHUTDOWN_TIMEOUT = 'NANOCODER_DEFAULT_SHUTDOWN_TIMEOUT';
export class ShutdownManager {
    handlers = new Map();
    isShuttingDown = false;
    timeoutMs;
    boundSigterm;
    boundSigint;
    boundUncaughtException;
    boundUnhandledRejection;
    constructor(options) {
        const envTimeout = process.env[ENV_SHUTDOWN_TIMEOUT];
        const parsedEnvTimeout = envTimeout ? parseInt(envTimeout, 10) : undefined;
        const isValidTimeout = Number.isFinite(parsedEnvTimeout);
        this.timeoutMs =
            options?.timeoutMs ??
                (isValidTimeout ? parsedEnvTimeout : undefined) ??
                DEFAULT_TIMEOUT_MS;
        this.boundSigterm = () => {
            void this.gracefulShutdown(0);
        };
        this.boundSigint = () => {
            void this.gracefulShutdown(0);
        };
        this.boundUncaughtException = (err) => {
            const logger = loggerProvider.getLogger();
            logger.fatal({ err }, 'Uncaught exception');
            void this.gracefulShutdown(1);
        };
        this.boundUnhandledRejection = (reason, promise) => {
            const logger = loggerProvider.getLogger();
            logger.fatal({ reason, promise }, 'Unhandled promise rejection');
            void this.gracefulShutdown(1);
        };
        this.setupSignalHandlers();
    }
    register(handler) {
        this.handlers.set(handler.name, handler);
    }
    unregister(name) {
        this.handlers.delete(name);
    }
    async gracefulShutdown(exitCode = 0) {
        if (this.isShuttingDown) {
            return;
        }
        this.isShuttingDown = true;
        const logger = loggerProvider.getLogger();
        logger.info('Graceful shutdown initiated', { exitCode });
        const sorted = Array.from(this.handlers.values()).sort((a, b) => a.priority - b.priority);
        const shutdownPromise = (async () => {
            for (const entry of sorted) {
                try {
                    logger.info(`Shutting down: ${entry.name}`);
                    await entry.handler();
                }
                catch (err) {
                    logger.error({ err }, `Shutdown handler failed: ${entry.name}`);
                }
            }
        })();
        const timeoutPromise = new Promise(resolve => {
            setTimeout(() => {
                logger.warn('Shutdown timeout reached, forcing exit');
                resolve();
            }, this.timeoutMs);
        });
        await Promise.race([shutdownPromise, timeoutPromise]);
        process.exit(exitCode);
    }
    setupSignalHandlers() {
        process.once('SIGTERM', this.boundSigterm);
        process.once('SIGINT', this.boundSigint);
        process.on('uncaughtException', this.boundUncaughtException);
        process.on('unhandledRejection', this.boundUnhandledRejection);
    }
    reset() {
        this.handlers.clear();
        this.isShuttingDown = false;
        process.removeListener('SIGTERM', this.boundSigterm);
        process.removeListener('SIGINT', this.boundSigint);
        process.removeListener('uncaughtException', this.boundUncaughtException);
        process.removeListener('unhandledRejection', this.boundUnhandledRejection);
    }
}
let instance = null;
export function getShutdownManager(options) {
    if (!instance) {
        instance = new ShutdownManager(options);
    }
    return instance;
}
export function resetShutdownManager() {
    if (instance) {
        instance.reset();
        instance = null;
    }
}
//# sourceMappingURL=shutdown-manager.js.map