/**
 * Federation membership store (SPOKE side): which remote teams THIS deployment
 * has joined, and the syncToken/hub needed to push bots + pull the shared roster.
 *
 * Storage: `{dataDir}/federation-memberships.json`, atomic writes. Keyed by
 * `${hubUrl}::${teamId}` so a deployment can join multiple teams / hubs.
 */
import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from 'node:fs';
import { join } from 'node:path';
import { randomUUID } from 'node:crypto';
function filePath(dataDir) {
    return join(dataDir, 'federation-memberships.json');
}
function keyOf(hubUrl, teamId) {
    return `${hubUrl}::${teamId}`;
}
function readFile(dataDir) {
    const fp = filePath(dataDir);
    if (!existsSync(fp))
        return {};
    try {
        const parsed = JSON.parse(readFileSync(fp, 'utf-8'));
        if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
            return parsed;
    }
    catch { /* corrupt */ }
    return {};
}
function writeFileAtomic(dataDir, data) {
    if (!existsSync(dataDir))
        mkdirSync(dataDir, { recursive: true });
    const fp = filePath(dataDir);
    const tmp = `${fp}.${process.pid}.${randomUUID()}.tmp`;
    writeFileSync(tmp, JSON.stringify(data, null, 2) + '\n', 'utf-8');
    renameSync(tmp, fp);
}
/** Record (or replace) a remote-team membership. */
export function addMembership(dataDir, m, now = Date.now()) {
    const data = readFile(dataDir);
    const full = { ...m, joinedAt: m.joinedAt ?? now };
    data[keyOf(m.hubUrl, m.teamId)] = full;
    writeFileAtomic(dataDir, data);
    return full;
}
/** All remote teams this deployment has joined. */
export function listMemberships(dataDir) {
    return Object.values(readFile(dataDir));
}
/** Find the membership whose delegationToken matches (verifies an incoming
 *  hub→spoke delegate call came from a hub this deployment actually joined). */
export function findMembershipByDelegationToken(dataDir, token) {
    if (!token)
        return null;
    return Object.values(readFile(dataDir)).find(m => m.delegationToken === token) ?? null;
}
/** Remove one membership. Returns true if removed. */
export function removeMembership(dataDir, hubUrl, teamId) {
    const data = readFile(dataDir);
    const key = keyOf(hubUrl, teamId);
    if (!data[key])
        return false;
    delete data[key];
    writeFileAtomic(dataDir, data);
    return true;
}
//# sourceMappingURL=federation-membership-store.js.map