/**
 * Teams Backup Service
 *
 * Provides automatic backup and restore functionality for teams data.
 *
 * Two layers of durability:
 *  1. **Live single-file backup** (`teams-backup.json`) — preserved for
 *     backward compat with the existing status / restore endpoints.
 *  2. **Rotating ring buffer** (N=30 snapshots in `teams-backup-history/`) —
 *     introduced by Persistence P0 (A2). Even if a corrupting save propagates
 *     to the live backup, the previous N-1 slots remain intact.
 *
 * @module services/core/teams-backup.service
 */
import type { Team } from '../../types/index.js';
/** Number of rotating snapshot slots to retain. */
export declare const MAX_HISTORY_SLOTS = 30;
/**
 * Shape of the backup file
 */
export interface TeamsBackup {
    /** ISO timestamp of when the backup was written */
    timestamp: string;
    /** Full team objects at time of backup */
    teams: Team[];
}
/**
 * Status returned by getBackupStatus
 */
export interface TeamsBackupStatus {
    /** Whether current teams are empty but backup has data */
    hasMismatch: boolean;
    /** Number of teams in the backup file */
    backupTeamCount: number;
    /** Number of teams currently in storage */
    currentTeamCount: number;
    /** ISO timestamp of the most recent backup */
    backupTimestamp: string | null;
}
/**
 * Single entry in the rotating-snapshot history.
 */
export interface TeamsBackupHistoryEntry {
    /** Slot index (0..MAX_HISTORY_SLOTS-1) */
    slot: number;
    /** ISO timestamp the snapshot was written */
    timestamp: string;
    /** Number of teams captured in the snapshot */
    teamCount: number;
    /** Whether this slot is the most recently written one */
    isHead: boolean;
}
/**
 * On-disk index that tracks the ring buffer.
 */
export interface TeamsBackupHistoryIndex {
    /** Slot index of the most recently written snapshot. -1 = empty. */
    head: number;
    /** Total snapshots written ever (monotonic; not the current count). */
    written: number;
    /** Per-slot metadata. Slots without data are omitted. */
    slots: Record<number, {
        timestamp: string;
        teamCount: number;
    }>;
}
/**
 * TeamsBackupService manages the live single-file backup AND a rotating
 * ring buffer of historical snapshots.
 *
 * @example
 * ```typescript
 * const backupService = TeamsBackupService.getInstance();
 * await backupService.updateBackup(teams);
 * const status = await backupService.getBackupStatus(currentTeams);
 * const history = await backupService.getBackupHistory();
 * const snapshot = await backupService.restoreFromSlot(2);
 * ```
 */
export declare class TeamsBackupService {
    private static instance;
    private backupPath;
    private historyDir;
    private historyIndexPath;
    private logger;
    /**
     * Create a new TeamsBackupService.
     *
     * @param crewlyHome - Path to the .crewly home directory
     */
    constructor(crewlyHome?: string);
    /**
     * Get singleton instance.
     *
     * @param crewlyHome - Optional override for the home directory
     * @returns TeamsBackupService instance
     */
    static getInstance(crewlyHome?: string): TeamsBackupService;
    /**
     * Clear singleton instance (for testing).
     */
    static clearInstance(): void;
    /**
     * Write or update the backup file with the current teams data.
     * Called after every successful saveTeam() or deleteTeam().
     *
     * Writes both the live single-file backup AND a new rotating-snapshot
     * slot. If history rotation fails, the live backup still proceeds —
     * we never want a history-write bug to block the primary durability path.
     *
     * @param teams - Current full list of teams
     */
    updateBackup(teams: Team[]): Promise<void>;
    /**
     * Read the backup file from disk.
     *
     * @returns The parsed backup or null if no backup exists
     */
    readBackup(): Promise<TeamsBackup | null>;
    /**
     * Check whether current teams data is empty but backup has data.
     *
     * @param currentTeams - The current teams from storage
     * @returns Backup status with mismatch flag
     */
    getBackupStatus(currentTeams: Team[]): Promise<TeamsBackupStatus>;
    /**
     * Get the backup file path (for testing).
     *
     * @returns Absolute path to the backup file
     */
    getBackupPath(): string;
    /**
     * Get the history directory path (for testing).
     *
     * @returns Absolute path to the rotating-snapshot directory
     */
    getHistoryDir(): string;
    /**
     * List all populated rotating-snapshot slots, newest first.
     *
     * @returns Array of slot metadata. Empty array if history is empty.
     */
    getBackupHistory(): Promise<TeamsBackupHistoryEntry[]>;
    /**
     * Read a single rotating-snapshot slot.
     *
     * @param slot - Slot index 0..MAX_HISTORY_SLOTS-1
     * @returns Parsed snapshot or null if slot is empty / corrupted
     */
    readSlot(slot: number): Promise<TeamsBackup | null>;
    /**
     * Restore from a specific rotating-snapshot slot. The caller is
     * responsible for re-saving each team via StorageService — this method
     * just returns the snapshot contents.
     *
     * @param slot - Slot index 0..MAX_HISTORY_SLOTS-1
     * @returns Snapshot to restore, or null if slot is empty
     */
    restoreFromSlot(slot: number): Promise<TeamsBackup | null>;
    /**
     * Read the rotating-snapshot index from disk.
     *
     * @returns Parsed index or null if it does not exist / is corrupted
     */
    private readHistoryIndex;
    /**
     * Write a new rotating snapshot, advancing the head pointer.
     *
     * Order matters: snapshot file written FIRST, then index. If the process
     * dies between the two writes, we end up with an unreferenced slot file
     * (harmless) rather than an index pointing at a half-written slot.
     *
     * @param teams - Teams to snapshot into the new slot
     */
    private writeRotatingSnapshot;
    /**
     * @returns A fresh empty history index (head=-1, no slots).
     */
    private emptyIndex;
}
//# sourceMappingURL=teams-backup.service.d.ts.map