/**
 * Sync worker smoke.
 *
 * Boots an in-process LocalSqliteStore + applies the seed, then exercises
 * `runSyncOnce` in two modes:
 *  - sync disabled: asserts the worker is a no-op and no hosted writes occur.
 *  - sync enabled with an in-process mock receiver: asserts every domain
 *    posts at least one envelope, replays are idempotent on a second pass,
 *    and serialized payloads contain no unsafe sentinels.
 *
 * The smoke does not start the bridge HTTP server. It boots a minimal
 * `http.createServer` mock as the hosted sync receiver to keep the harness
 * permission-safe.
 */
import { createServer } from "node:http";
import { once } from "node:events";
import { LocalSqliteStore } from "../persistence/LocalSqliteStore.js";
import { applySeed } from "../persistence/seed/applySeed.js";
import { runSyncOnce } from "../runs/syncWorker.js";
const ALL_DOMAINS = {
    runs: true,
    runtimeEvents: true,
    proofEvidence: true,
    permissionActivity: true,
    repositories: true,
    onboarding: true,
    settings: true,
    reviewQueue: true,
};
const UNSAFE_MARKERS = [
    "/Users/",
    ".sqlite",
    "Bearer ",
    "patchTrailLocalHandoff=",
    "sk-",
    "AIza",
];
const TEST_SYNC_SIGNING_KEY = "WbyPvfG3JtDdht6qN3-ow__ZHe0vvHyNHoj2271H7z4";
const TEST_SYNC_KEY_ID = "sync-key-smoke-001";
function findUnsafeMarker(text) {
    for (const m of UNSAFE_MARKERS) {
        if (text.includes(m))
            return m;
    }
    return null;
}
async function startMockReceiver() {
    const bodies = [];
    const server = createServer((req, res) => {
        if (typeof req.headers["x-patchtrail-sync-signature"] !== "string" ||
            typeof req.headers["x-patchtrail-sync-key-id"] !== "string" ||
            typeof req.headers["x-patchtrail-sync-audience"] !== "string" ||
            typeof req.headers["x-patchtrail-sync-body-sha256"] !== "string" ||
            typeof req.headers["x-patchtrail-sync-nonce"] !== "string") {
            res.writeHead(401, { "content-type": "application/json" });
            res.end(JSON.stringify({ status: "rejected" }));
            return;
        }
        let body = "";
        req.on("data", (chunk) => (body += chunk));
        req.on("end", () => {
            bodies.push(body);
            res.writeHead(200, { "content-type": "application/json" });
            res.end(JSON.stringify({ status: "accepted" }));
        });
    });
    server.listen(0, "127.0.0.1");
    await once(server, "listening");
    const address = server.address();
    if (typeof address !== "object" || address === null) {
        throw new Error("mock receiver did not bind");
    }
    return {
        url: `http://127.0.0.1:${address.port}/api/v1/sync/projections`,
        audience: `http://127.0.0.1:${address.port}`,
        bodies,
        close: () => new Promise((resolve) => {
            server.close(() => resolve());
        }),
    };
}
export async function runSyncSmoke() {
    const result = {
        status: "passed",
        disabled: { posted: 0, succeeded: 0 },
        enabled: {
            posted: 0,
            succeeded: 0,
            failed: 0,
            skipped: 0,
            domainsPosted: [],
        },
        replay: { posted: 0, skipped: 0 },
        unsafeLeak: null,
    };
    const store = await LocalSqliteStore.open(":memory:");
    applySeed(store, { enabled: true, domains: ALL_DOMAINS });
    // Phase 1: sync disabled => no hosted writes.
    const disabledCfg = {
        enabled: false,
        endpointUrl: null,
        signingKey: null,
        keyId: null,
        audience: null,
        retryBudget: 5,
        timeoutMs: 10_000,
        intervalMs: 30_000,
        domains: ALL_DOMAINS,
    };
    const disabled = await runSyncOnce(store, disabledCfg, {
        workspaceIds: ["ws-seed-local"],
    });
    result.disabled.posted = disabled.posted;
    result.disabled.succeeded = disabled.succeeded;
    if (disabled.posted !== 0) {
        result.status = "failed";
        result.reason = "sync-disabled-still-posted";
        return result;
    }
    // Phase 2: sync enabled + in-process mock receiver.
    const receiver = await startMockReceiver();
    try {
        const enabledCfg = {
            enabled: true,
            endpointUrl: receiver.url,
            signingKey: TEST_SYNC_SIGNING_KEY,
            keyId: TEST_SYNC_KEY_ID,
            audience: receiver.audience,
            retryBudget: 5,
            timeoutMs: 10_000,
            intervalMs: 30_000,
            domains: ALL_DOMAINS,
        };
        const enabled = await runSyncOnce(store, enabledCfg, {
            workspaceIds: ["ws-seed-local"],
        });
        result.enabled.posted = enabled.posted;
        result.enabled.succeeded = enabled.succeeded;
        result.enabled.failed = enabled.failed;
        result.enabled.skipped = enabled.skipped;
        for (const [domain, counts] of Object.entries(enabled.perDomain)) {
            if (counts.posted > 0)
                result.enabled.domainsPosted.push(domain);
        }
        // Phase 3: replay => no new posts, all skipped.
        const replay = await runSyncOnce(store, enabledCfg, {
            workspaceIds: ["ws-seed-local"],
        });
        result.replay.posted = replay.posted;
        result.replay.skipped = replay.skipped;
        // Phase 4: scan every posted body for unsafe sentinels.
        for (const body of receiver.bodies) {
            const hit = findUnsafeMarker(body);
            if (hit) {
                result.unsafeLeak = hit;
                result.status = "failed";
                result.reason = `unsafe-sentinel-in-posted-body:${hit}`;
                return result;
            }
        }
    }
    finally {
        await receiver.close();
    }
    if (result.enabled.posted === 0) {
        result.status = "failed";
        result.reason = "no-posts-with-sync-enabled";
        return result;
    }
    if (result.replay.posted !== 0) {
        result.status = "failed";
        result.reason = "replay-posted-instead-of-skipping";
        return result;
    }
    return result;
}
