import { getRunStore } from './index.js';
import { removeRunExecutionJob } from '../queue/index.js';
import { appendRunLog, buildSentinelFailureLog, buildSentinelFailureOutput, emitSentinelKilledSse, } from '../security/sentinel-run-failure.js';
import { publishSentinelRunKillFireAndForget } from '../adapters/redis-sentinel-publisher.js';
import { createLogger } from '@4runr/shared';
const logger = createLogger('Gateway:RunKill');
const TERMINAL_STATUSES = ['killed', 'completed', 'failed'];
let sideEffects = {};
export function setRunKillSideEffects(effects) {
    sideEffects = effects;
}
export function isTerminalRunStatus(status) {
    return TERMINAL_STATUSES.includes(status);
}
export async function applyRunKill(runId, reason) {
    const store = getRunStore();
    const run = await store.getRunById(runId);
    if (!run) {
        throw new Error(`Run not found: ${runId}`);
    }
    if (isTerminalRunStatus(run.status)) {
        logger.info('Run kill skipped — already terminal', { runId, status: run.status });
        return {
            applied: false,
            idempotent: true,
            runId,
            status: run.status,
        };
    }
    if (run.status === 'queued') {
        try {
            await removeRunExecutionJob(runId);
        }
        catch (error) {
            logger.warn('Failed to remove queued job during kill', {
                runId,
                error: error instanceof Error ? error.message : String(error),
            });
        }
    }
    const logEntry = {
        timestamp: new Date().toISOString(),
        level: 'error',
        message: buildSentinelFailureLog(reason),
    };
    await store.updateRunStatus(runId, 'killed', {
        completedAt: new Date().toISOString(),
        output: buildSentinelFailureOutput(reason),
        logs: appendRunLog(run.logs, logEntry),
    });
    sideEffects.decRunsActive?.();
    const connections = sideEffects.getSseConnections?.(runId);
    if (connections) {
        connections.forEach((connection) => {
            emitSentinelKilledSse(connection, runId, reason);
            sideEffects.onSseMessage?.();
        });
    }
    sideEffects.deleteEventStream?.(runId);
    publishSentinelRunKillFireAndForget(runId, reason);
    logger.info('Run killed in store', { runId, reason });
    return {
        applied: true,
        idempotent: false,
        runId,
        status: 'killed',
    };
}
//# sourceMappingURL=run-kill.js.map