/**
 * Reconciler — single background loop that drains the SyncQueue, polls
 * for server changes, and emits state events the UI listens for.
 *
 * Local-first contract: the Reconciler is the ONLY code path that touches
 * IMAP / Gmail API on behalf of UI actions. UI handlers commit locally
 * and enqueue; the Reconciler picks up and mirrors. Reads from the UI
 * never await the Reconciler.
 *
 * What this owns today:
 * - body-fetch lane: drains `SyncQueue.nextBodyFetch()`, calls
 *   `imapManager.fetchMessageBody`, emits `bodyAvailable` / `bodyFetchError`.
 *   This is the new piece; previously body fetches happened inline on
 *   every getMessage call.
 * - sync-state pill events: emits `syncStateChanged` so the UI can show
 *   "Sync OK / Syncing N items".
 *
 * What it delegates (intentional — no duplication):
 * - message-action drain: ImapManager already runs a 30s actionsInterval
 *   that processes both outbox (processSendActions) and sync_actions
 *   (processSyncActions) per account. Per plan decision #5, outbox stays
 *   under ImapManager; we don't fork that work.
 * - poll loops (per-account quick check, full sync, prefetch, tombstone
 *   prune): all owned by ImapManager's startPeriodicSync. The Reconciler
 *   does NOT shadow them — back-pressure on those timers can be added
 *   later via a single `setBackPressure(level)` hook.
 *
 * Part of docs/local-first-plan.md (step 4).
 */
import type { ImapManager } from "@bobfrankston/mailx-imap";
import type { MailxDB } from "@bobfrankston/mailx-store";
import type { SyncQueue } from "./sync-queue.js";
export interface ReconcilerOptions {
    /** Max concurrent body fetches across all accounts (in addition to
     *  per-account semaphore in ImapManager). Keeps the interactive lane
     *  responsive even when prefetch is hammering. */
    bodyFetchConcurrency?: number;
    /** Periodic emit of syncStateChanged — drives the UI status pill. */
    statusEmitIntervalMs?: number;
    /** How often to fire the prefetch tick. Default 60s. */
    prefetchIntervalMs?: number;
    /** First prefetch fires this soon after start so the "not downloaded"
     *  dots fill in without making the user wait a minute. */
    prefetchInitialDelayMs?: number;
    /** Skip prefetch when the interactive body-fetch lane has at least
     *  this many items pending. Back-pressure keeps clicks responsive. */
    prefetchBackpressureThreshold?: number;
    /** Tombstone prune interval — bookkeeping only, hourly default. */
    tombstonePruneIntervalMs?: number;
    /** Tombstone retention — local-delete records older than this are
     *  removed by the periodic prune. */
    tombstoneRetentionDays?: number;
}
export declare class Reconciler {
    private db;
    private imapManager;
    private queue;
    private opts;
    private running;
    private statusTimer;
    private prefetchTimer;
    private tombstoneTimer;
    private inFlightFetches;
    /** Last status payload — used to suppress no-op syncStateChanged events.
     *  During a heavy multi-folder sync the 5s tick fires a lot of identical
     *  events; the WebView's event handler runs DOM work for each, which
     *  stacks up under load. Diff-only emits keep the channel quiet. */
    private lastStatus;
    constructor(db: MailxDB, imapManager: ImapManager, queue: SyncQueue, opts?: ReconcilerOptions);
    start(): void;
    stop(): void;
    /** Hourly bookkeeping — drop tombstones older than the retention window
     *  so the deleted-message lookup stays fast. */
    private runTombstonePrune;
    /** Fire prefetchBodies on each account unless the interactive body-fetch
     *  lane has user-clicked work pending — in which case skip this tick.
     *  ImapManager's per-account `prefetchingAccounts` guard de-dupes if
     *  the previous tick is still in flight. */
    private runPrefetchTick;
    /** User-visible "sync now" — runs an immediate poll on all accounts
     *  (or just one) without waiting for the next periodic tick. */
    syncNow(accountId?: string): void;
    /** Drain the body-fetch lane up to `bodyFetchConcurrency`. Each
     *  fetch is fire-and-forget; on completion it kicks the pump again
     *  so a queue that grows during work stays drained. */
    private pumpBodyFetches;
    /** External nudge — call after enqueueing a high-priority body fetch. */
    kick(): void;
}
//# sourceMappingURL=reconciler.d.ts.map