// storage/outbound-webhook-store.ts — Persistence for outbound webhook configs (SPEC-281)
import { join } from 'node:path';
import { createHash } from 'node:crypto';
import { readJson, writeJson, projectDataDir, hashProjectPath } from './base-store.js';
import { withFileLock } from './file-mutex.js';
// ---------------------------------------------------------------------------
// Path helpers
// ---------------------------------------------------------------------------
function webhooksPath(projectId) {
    return join(projectDataDir(projectId), 'webhooks.json');
}
function deliveriesPath(projectId) {
    return join(projectDataDir(projectId), 'webhook-deliveries.json');
}
// ---------------------------------------------------------------------------
// ID generation
// ---------------------------------------------------------------------------
function generateWebhookId(url, createdAt) {
    return createHash('sha256').update(`${url}:${createdAt}`).digest('hex').slice(0, 12);
}
// ---------------------------------------------------------------------------
// Config CRUD
// ---------------------------------------------------------------------------
export async function listWebhooks(projectPath) {
    const projectId = hashProjectPath(projectPath);
    return readJson(webhooksPath(projectId), []);
}
export async function getWebhook(projectPath, webhookId) {
    const configs = await listWebhooks(projectPath);
    return configs.find((c) => c.id === webhookId) ?? null;
}
export async function addWebhook(projectPath, config) {
    const projectId = hashProjectPath(projectPath);
    const filePath = webhooksPath(projectId);
    return withFileLock(filePath, async () => {
        const existing = await readJson(filePath, []);
        const createdAt = new Date().toISOString();
        const newConfig = {
            ...config,
            id: generateWebhookId(config.url, createdAt),
            createdAt,
            active: true,
        };
        existing.push(newConfig);
        await writeJson(filePath, existing);
        return newConfig;
    });
}
export async function deactivateWebhook(projectPath, webhookId) {
    const projectId = hashProjectPath(projectPath);
    const filePath = webhooksPath(projectId);
    return withFileLock(filePath, async () => {
        const configs = await readJson(filePath, []);
        const idx = configs.findIndex((c) => c.id === webhookId);
        if (idx === -1) {
            return null;
        }
        const existing = configs[idx];
        if (existing === undefined) {
            return null;
        }
        const updated = { ...existing, active: false };
        configs[idx] = updated;
        await writeJson(filePath, configs);
        return updated;
    });
}
// ---------------------------------------------------------------------------
// Delivery log (last 50 per webhook)
// ---------------------------------------------------------------------------
const MAX_DELIVERIES = 50;
export async function appendDelivery(projectPath, delivery) {
    const projectId = hashProjectPath(projectPath);
    const filePath = deliveriesPath(projectId);
    await withFileLock(filePath, async () => {
        const deliveries = await readJson(filePath, []);
        // Remove oldest entries beyond MAX_DELIVERIES per webhook
        const forThisWebhook = deliveries.filter((d) => d.webhookId === delivery.webhookId);
        if (forThisWebhook.length >= MAX_DELIVERIES) {
            const overflow = forThisWebhook.length - MAX_DELIVERIES + 1;
            let removed = 0;
            const trimmed = deliveries.filter((d) => {
                if (d.webhookId === delivery.webhookId && removed < overflow) {
                    removed++;
                    return false;
                }
                return true;
            });
            trimmed.push(delivery);
            await writeJson(filePath, trimmed);
            return;
        }
        deliveries.push(delivery);
        await writeJson(filePath, deliveries);
    });
}
export async function getDeliveries(projectPath, webhookId) {
    const projectId = hashProjectPath(projectPath);
    const deliveries = await readJson(deliveriesPath(projectId), []);
    if (webhookId !== undefined) {
        return deliveries.filter((d) => d.webhookId === webhookId);
    }
    return deliveries;
}
// ---------------------------------------------------------------------------
// Active webhooks filtered by event
// ---------------------------------------------------------------------------
export async function getActiveWebhooksForEvent(projectPath, event) {
    const configs = await listWebhooks(projectPath);
    return configs.filter((c) => c.active && (c.events.length === 0 || c.events.includes(event)));
}
//# sourceMappingURL=outbound-webhook-store.js.map