/**
 * presence-sync — read each connected agent's HF status (via the
 * cross-plugin `globalThis.__hfAgentStatus.get(agentId)` exposed by
 * HarborForge.OpenclawPlugin) and push diffs to Fabric.Backend.Guild
 * `PUT /agents/:userId/presence` so the backend can apply busy-discard
 * on `announce`-type channel deliveries.
 *
 * Push model: we only PUT when an agent's status actually changes
 * (since the last push). The HF-side accessor has its own TTL cache
 * to absorb the every-30s polling.
 *
 * If HF plugin isn't loaded (`__hfAgentStatus` undefined), the loop
 * is a no-op — Fabric backend defaults presence to 'unknown' which is
 * treated as not-busy. Announce-channel delivery still works; busy
 * filtering simply doesn't kick in.
 */
export class PresenceSync {
    logger;
    timer = null;
    lastStatus = new Map(); // by agentId
    accounts = new Map();
    constructor(logger) {
        this.logger = logger;
    }
    setAccounts(accounts) {
        this.accounts.clear();
        for (const a of accounts)
            this.accounts.set(a.agentId, a);
    }
    start(intervalMs = 30_000) {
        if (this.timer)
            return;
        this.timer = setInterval(() => {
            this.tick().catch((err) => this.logger.warn(`fabric: presence-sync error: ${String(err)}`));
        }, intervalMs);
        // run once immediately so initial state lands fast
        void this.tick();
    }
    stop() {
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = null;
        }
    }
    async tick() {
        const bridge = globalThis['__hfAgentStatus'];
        if (!bridge || typeof bridge.get !== 'function')
            return; // HF plugin not loaded — skip
        for (const [agentId, acct] of this.accounts) {
            let status;
            try {
                status = await bridge.get(agentId);
            }
            catch {
                continue;
            }
            if (!status)
                continue;
            if (this.lastStatus.get(agentId) === status)
                continue; // no change → no PUT
            try {
                const url = `${acct.guildBaseUrl.replace(/\/$/, '')}/agents/${encodeURIComponent(acct.fabricUserId)}/presence`;
                const res = await fetch(url, {
                    method: 'PUT',
                    headers: {
                        'content-type': 'application/json',
                        'x-api-key': acct.fabricApiKey,
                    },
                    body: JSON.stringify({ status, source: 'hf-plugin' }),
                });
                if (res.ok) {
                    this.lastStatus.set(agentId, status);
                    this.logger.info(`fabric: presence-sync ${agentId} → ${status}`);
                }
                else {
                    this.logger.warn(`fabric: presence-sync PUT ${agentId} failed: ${res.status}`);
                }
            }
            catch (err) {
                this.logger.warn(`fabric: presence-sync PUT ${agentId} threw: ${String(err)}`);
            }
        }
    }
}
