/**
 * Thread Status Queue Service
 *
 * Tracks the lifecycle of every inbound message thread across platforms
 * (Slack, GChat, Telegram, etc.). On orchestrator restart, non-terminal
 * threads are recovered and re-enqueued so no user messages are silently dropped.
 *
 * Persistence is debounced and written to ~/.crewly/thread-status-queue.json
 * using atomic file I/O to prevent corruption.
 *
 * @module services/messaging/thread-status-queue
 */
import type { ThreadStatus, ThreadStatusEntry, TrackInboundInput, ThreadStatusStats, ReplyStatus } from '../../types/thread-status.types.js';
/**
 * Minimal interface for SchedulerService to avoid circular imports.
 * Used to create follow-up checks when a thread is marked as replied_to_follow_up.
 */
export interface ISchedulerServiceLike {
    scheduleCheck(targetSession: string, minutes: number, message: string, type?: string, options?: {
        label?: string;
    }): string;
    cancelCheck(checkId: string): void;
}
/**
 * Minimal interface for EventBusService to avoid circular imports.
 * Uses unknown for eventType/filter to avoid importing event-bus types.
 */
export interface IEventBusServiceLike {
    subscribe(input: unknown): {
        id: string;
    };
    unsubscribe(subscriptionId: string): boolean;
}
/**
 * Minimal interface for MessageQueueService to avoid circular imports.
 * Used during restart recovery to re-enqueue pending threads.
 */
export interface IMessageQueueServiceLike {
    enqueue(input: {
        content: string;
        conversationId: string;
        source: string;
        sourceMetadata?: Record<string, unknown>;
        targetSession?: string;
    }): unknown;
}
/**
 * Minimal interface for checking agent working status.
 * Used during recovery to determine if delegated agents have completed.
 */
export interface IAgentStatusCheckerLike {
    getAgentWorkingStatus(sessionName: string): Promise<'idle' | 'in_progress' | 'unknown'>;
}
/**
 * Callback for sending platform-specific confirmation messages during recovery.
 * e.g., "I am back online. I see your message: {preview}. Let me handle it now."
 *
 * @param entry - The thread entry to confirm
 * @returns Promise resolving when the confirmation is sent
 */
export type RecoveryConfirmCallback = (entry: ThreadStatusEntry) => Promise<void>;
/**
 * Tracks active follow-up subscriptions so they can be cancelled
 * when the user replies before the scheduled check fires.
 */
interface FollowUpTracking {
    /** ID of the scheduled check */
    scheduledCheckId: string;
    /** ID of the event bus subscription */
    eventSubscriptionId: string;
}
/**
 * Service that maintains a persistent queue of thread statuses.
 * Constructed with a crewly home directory path for disk persistence.
 *
 * Lifecycle: enqueued → delivered → replied_* (terminal or waiting_actions)
 *
 * @example
 * ```typescript
 * const svc = new ThreadStatusQueueService('/home/user/.crewly');
 * await svc.loadPersistedState();
 *
 * const entry = svc.trackInbound({
 *   source: 'slack',
 *   threadKey: 'C123:170743.001',
 *   conversationId: 'conv-1',
 *   messagePreview: 'Deploy the new feature',
 * });
 *
 * svc.markDelivered('C123:170743.001');
 * svc.markReplied('C123:170743.001', 'replied_completed');
 * ```
 */
export declare class ThreadStatusQueueService {
    /** Singleton instance */
    private static instance;
    /** Logger for this service */
    private logger;
    /** All tracked thread entries, keyed by threadKey for O(1) lookup */
    private entries;
    /** Path to the persistence file, or null if init() has not been called */
    private persistPath;
    /** Debounce timer for batching persistence writes */
    private persistTimer;
    /** ISO timestamp of last cleanup run */
    private lastCleanupAt;
    /** Scheduler service for creating follow-up checks */
    private schedulerService;
    /** Event bus for subscribing to message:received events */
    private eventBusService;
    /** Tracks active follow-up subscriptions keyed by threadKey */
    private followUpTracking;
    /**
     * Creates a new ThreadStatusQueueService.
     * Use getInstance() for singleton access, or construct directly for testing.
     *
     * @param crewlyHome - Optional crewly home directory path for immediate initialization
     */
    constructor(crewlyHome?: string);
    /**
     * Returns the singleton instance of ThreadStatusQueueService.
     * Call init() after this to set the persistence path.
     *
     * @returns The singleton instance
     */
    static getInstance(): ThreadStatusQueueService;
    /**
     * Resets the singleton instance. For testing only.
     */
    static resetInstance(): void;
    /**
     * Loads persisted state from disk.
     * If the file doesn't exist or is corrupted, starts with an empty queue.
     */
    loadPersistedState(): Promise<void>;
    /**
     * Records a new inbound thread message with status `enqueued`.
     * If a thread with the same threadKey already exists, the existing entry is returned.
     *
     * @param input - Inbound message details
     * @returns The created (or existing) ThreadStatusEntry
     */
    trackInbound(input: TrackInboundInput): ThreadStatusEntry;
    /**
     * Transitions a thread from `enqueued` (or `error`) to `delivered`.
     * No-op if thread is already in a terminal or later status.
     *
     * @param threadKey - Platform-specific thread identifier
     * @throws Error if threadKey is not found
     */
    markDelivered(threadKey: string): void;
    /**
     * Set the SchedulerService instance for creating follow-up checks.
     * Called during server initialization.
     *
     * @param service - The SchedulerService instance (or compatible interface)
     */
    setSchedulerService(service: ISchedulerServiceLike): void;
    /**
     * Set the EventBusService instance for subscribing to message events.
     * Called during server initialization.
     *
     * @param service - The EventBusService instance (or compatible interface)
     */
    setEventBusService(service: IEventBusServiceLike): void;
    /**
     * Transitions a thread to one of the replied_* statuses.
     * Sets the repliedAt timestamp.
     *
     * When status is `replied_to_follow_up`, automatically:
     * 1. Creates a scheduled check (default 5 min) to verify user replied
     * 2. Subscribes to message:received events for this thread's conversation
     * 3. On user reply: cancels the scheduled check and transitions to replied_completed
     *
     * @param threadKey - Platform-specific thread identifier
     * @param status - One of: replied_completed, replied_waiting_actions, replied_to_follow_up
     * @throws Error if threadKey is not found or status is not a valid reply status
     */
    markReplied(threadKey: string, status: ReplyStatus): void;
    /**
     * Handles a user reply to a follow-up thread.
     * Cancels the scheduled check, removes the event subscription,
     * and transitions the thread to replied_completed (or re-enqueues).
     *
     * @param threadKey - Platform-specific thread identifier
     */
    handleFollowUpReply(threadKey: string): void;
    /**
     * Returns the active follow-up tracking for a thread, if any.
     * Useful for testing and debugging.
     *
     * @param threadKey - Platform-specific thread identifier
     * @returns The follow-up tracking info, or null
     */
    getFollowUpTracking(threadKey: string): FollowUpTracking | null;
    /**
     * Records that an agent was delegated work from this thread.
     *
     * @param threadKey - Platform-specific thread identifier
     * @param agentSession - Session name of the delegated agent
     * @throws Error if threadKey is not found
     */
    addDelegatedAgent(threadKey: string, agentSession: string): void;
    /**
     * Transitions a `replied_waiting_actions` thread to `replied_completed`
     * when all delegated agents have finished their work.
     *
     * @param threadKey - Platform-specific thread identifier
     * @throws Error if threadKey is not found
     */
    markDelegationsComplete(threadKey: string): void;
    /**
     * Returns all entries not in a terminal status. Used for restart recovery.
     *
     * @returns Array of non-terminal ThreadStatusEntry objects
     */
    getPendingThreads(): ThreadStatusEntry[];
    /**
     * Returns all entries matching the given status.
     *
     * @param status - The ThreadStatus to filter by
     * @returns Array of matching ThreadStatusEntry objects
     */
    getByStatus(status: ThreadStatus): ThreadStatusEntry[];
    /**
     * Retrieves a specific entry by threadKey.
     *
     * @param threadKey - Platform-specific thread identifier
     * @returns The entry, or null if not found
     */
    get(threadKey: string): ThreadStatusEntry | null;
    /**
     * Find a thread entry by its conversationId.
     *
     * Useful when the caller has a conversationId (e.g. from chat history)
     * but not the threadKey. Scans all entries — O(n) but the set is small.
     *
     * @param conversationId - The conversation ID to search for
     * @returns The most recently updated matching entry, or null
     */
    getByConversationId(conversationId: string): ThreadStatusEntry | null;
    /**
     * Finds a thread status entry by its queueMessageId.
     * Returns the most recently updated entry if multiple match.
     *
     * @param queueMessageId - The queue message ID to search for
     * @returns The most recently updated matching entry, or null
     */
    getByQueueMessageId(queueMessageId: string): ThreadStatusEntry | null;
    /**
     * Expires entries that have been in a non-terminal status longer than maxAgeMinutes.
     * Transitions them to `expired`.
     *
     * @param maxAgeMinutes - Maximum age in minutes (defaults to STALE_TIMEOUT_MINUTES)
     * @returns Number of entries expired
     */
    expireStale(maxAgeMinutes?: number): number;
    /**
     * Removes terminal entries older than retentionHours.
     * Also enforces MAX_ENTRIES by pruning oldest terminal entries first.
     *
     * @param retentionHours - Hours to retain terminal entries (defaults to CLEANUP_RETENTION_HOURS)
     * @returns Number of entries removed
     */
    cleanup(retentionHours?: number): number;
    /**
     * Returns statistics for monitoring the thread status queue.
     *
     * @returns Stats snapshot including total, per-status counts, and oldest pending timestamp
     */
    getStats(): ThreadStatusStats;
    /**
     * Initializes the service with a crewly home directory for persistence.
     * Must be called before loadPersistedState() when using getInstance().
     *
     * @param crewlyHome - Absolute path to the crewly home directory (e.g. ~/.crewly)
     */
    init(crewlyHome: string): void;
    /**
     * Public convenience method: optionally re-inits the persist path,
     * then loads persisted state from disk.
     *
     * @param crewlyHome - Optional crewly home directory to re-initialize with
     */
    load(crewlyHome?: string): Promise<void>;
    /**
     * Immediately flushes the current state to disk. Call during graceful shutdown
     * to ensure no in-memory mutations are lost.
     */
    persist(): Promise<void>;
    /**
     * Returns all entries in the queue. Used for the thread-status API.
     *
     * @returns Array of all ThreadStatusEntry objects
     */
    getAllEntries(): ThreadStatusEntry[];
    /**
     * Recovers pending threads after an orchestrator restart.
     * Loads persisted state and handles each thread based on its status:
     *
     * 1. **enqueued/delivered/error** — Send a "I'm back online" confirmation
     *    via the platform, then re-enqueue for orchestrator processing.
     * 2. **replied_to_follow_up** — Re-setup follow-up tracking (scheduled
     *    check + event subscription) to continue waiting for user reply.
     * 3. **replied_waiting_actions** — Check delegated agent statuses. If all
     *    agents are done, transition to replied_completed. Otherwise keep waiting.
     * 4. **replied_completed/expired** — Already terminal, skip.
     *
     * @param messageQueueService - The message queue service for re-enqueuing
     * @param options - Optional callbacks for agent status checking and platform confirmations
     * @returns Summary of recovery actions taken
     */
    recoverPendingThreads(messageQueueService: IMessageQueueServiceLike, options?: {
        agentStatusChecker?: IAgentStatusCheckerLike;
        confirmCallback?: RecoveryConfirmCallback;
    }): Promise<{
        loaded: number;
        reEnqueued: number;
        followUpRestored: number;
        waitingActionsChecked: number;
        delegationsCompleted: number;
        expired: number;
        cleaned: number;
    }>;
    /**
     * Cleans up timers and follow-up tracking. Call on shutdown.
     */
    destroy(): void;
    /**
     * Retrieves an entry by threadKey or throws an error with a descriptive message.
     *
     * @param threadKey - Platform-specific thread identifier
     * @param caller - Name of the calling method (for error messages)
     * @returns The found entry
     * @throws Error if entry is not found
     */
    private getOrThrow;
    /**
     * Sets up follow-up tracking for a replied_to_follow_up thread.
     * Creates a scheduled check and an event subscription so that if
     * the user replies, the check is cancelled and the thread is completed.
     *
     * @param threadKey - Platform-specific thread identifier
     * @param entry - The thread status entry
     */
    private setupFollowUpTracking;
    /**
     * Schedules a debounced persistence write to disk.
     * Multiple mutations within PERSIST_DEBOUNCE_MS are batched into a single write.
     */
    private schedulePersist;
    /**
     * Writes the current queue state to disk atomically.
     */
    private persistToDisk;
}
export {};
//# sourceMappingURL=thread-status-queue.service.d.ts.map