import { getRedisClient } from '../db/redis.js';
import { createLogger } from '@4runr/shared';
import { buildSentinelFailureOutput, parsePolicyFromKillReason, } from '../security/sentinel-run-failure.js';
import { sentinelKillsTotal, sentinelPolicyViolationsTotal, } from '../metrics/index.js';
const logger = createLogger('Gateway:Sentinel:RedisPublisher');
export async function publishSentinelEvent(event) {
    try {
        const redisClient = await getRedisClient();
        if (!redisClient) {
            return;
        }
        const channel = `sentinel:${event.type}`;
        const message = JSON.stringify(event);
        await redisClient.publish(channel, message);
        logger.debug('Published Sentinel event to Redis', {
            channel,
            runId: event.runId,
            type: event.type,
        });
    }
    catch (error) {
        logger.error('Failed to publish Sentinel event to Redis', {
            runId: event.runId,
            type: event.type,
            error: error instanceof Error ? error.message : String(error),
        });
    }
}
export function buildPolicyViolationEvent(runId, violation, timestamp = Date.now()) {
    return {
        type: 'policy.violation',
        runId,
        timestamp,
        data: { ...violation },
    };
}
export function buildKillEvent(runId, reason, trigger, timestamp = Date.now()) {
    return {
        type: 'kill',
        runId,
        timestamp,
        data: {
            reason,
            trigger,
            source: 'sentinel',
            output: buildSentinelFailureOutput(reason),
            policy: parsePolicyFromKillReason(reason),
        },
    };
}
export function buildAuditLogEvent(runId, action, payload, timestamp = Date.now()) {
    return {
        type: 'audit.log',
        runId,
        timestamp,
        data: { action, ...payload },
    };
}
function resolveKillTrigger(reason) {
    if (reason === 'manual_cancellation') {
        return 'manual';
    }
    if (reason.startsWith('policy_violation:')) {
        return 'policy';
    }
    return 'operator';
}
export async function publishSentinelRunKill(runId, reason) {
    const trigger = resolveKillTrigger(reason);
    sentinelKillsTotal.inc({ trigger });
    await publishSentinelEvent(buildKillEvent(runId, reason, trigger));
    await publishSentinelEvent(buildAuditLogEvent(runId, 'kill', {
        reason,
        trigger,
        output: buildSentinelFailureOutput(reason),
    }));
}
export async function publishSentinelPolicyViolation(runId, violation) {
    sentinelPolicyViolationsTotal.inc({ policy: violation.policy });
    await publishSentinelEvent(buildPolicyViolationEvent(runId, violation));
    await publishSentinelEvent(buildAuditLogEvent(runId, 'policy_violation', {
        policy: violation.policy,
        reason: violation.reason,
        threshold: violation.threshold,
        actual: violation.actual,
        action: 'deny',
    }));
}
export function publishSentinelRunKillFireAndForget(runId, reason) {
    void publishSentinelRunKill(runId, reason);
}
export function publishSentinelPolicyViolationFireAndForget(runId, violation) {
    void publishSentinelPolicyViolation(runId, violation);
}
//# sourceMappingURL=redis-sentinel-publisher.js.map