/**
 * Messaging Types Module
 *
 * Type definitions for the centralized message queue system.
 * All chat and Slack messages are enqueued into a FIFO queue,
 * processed one-at-a-time, and responses are routed back to the
 * correct source (WebSocket for chat, thread reply for Slack).
 *
 * @module types/messaging
 */
import { MESSAGE_SOURCES } from '../constants.js';
// Re-export for backwards compatibility
export { MESSAGE_SOURCES };
// =============================================================================
// Enums and Constants
// =============================================================================
/**
 * Valid message source values as a tuple (for .includes() validation).
 * Derived from the canonical MESSAGE_SOURCES object in constants.ts.
 */
export const MESSAGE_SOURCE_VALUES = Object.values(MESSAGE_SOURCES);
/**
 * Valid queue message statuses
 */
export const QUEUE_MESSAGE_STATUSES = ['pending', 'processing', 'completed', 'failed', 'cancelled'];
// =============================================================================
// Persistence Types
// =============================================================================
/** Current version of the persisted queue state format */
export const PERSISTED_QUEUE_VERSION = 1;
// =============================================================================
// Persistence Helpers
// =============================================================================
/**
 * Convert a QueuedMessage to a PersistedMessage by stripping function-valued
 * sourceMetadata entries (e.g. slackResolve callbacks that can't be serialized).
 *
 * @param msg - The queued message to convert
 * @returns A serializable PersistedMessage
 */
export function toPersistedMessage(msg) {
    const persisted = {
        id: msg.id,
        content: msg.content,
        conversationId: msg.conversationId,
        source: msg.source,
        status: msg.status,
        enqueuedAt: msg.enqueuedAt,
    };
    if (msg.processingStartedAt !== undefined) {
        persisted.processingStartedAt = msg.processingStartedAt;
    }
    if (msg.completedAt !== undefined) {
        persisted.completedAt = msg.completedAt;
    }
    if (msg.error !== undefined) {
        persisted.error = msg.error;
    }
    if (msg.response !== undefined) {
        persisted.response = msg.response;
    }
    if (msg.retryCount !== undefined && msg.retryCount > 0) {
        persisted.retryCount = msg.retryCount;
    }
    if (msg.deliveredAt !== undefined) {
        persisted.deliveredAt = msg.deliveredAt;
    }
    if (msg.sourceMetadata) {
        const cleaned = {};
        let hasEntries = false;
        for (const [key, value] of Object.entries(msg.sourceMetadata)) {
            if (typeof value !== 'function') {
                cleaned[key] = value;
                hasEntries = true;
            }
        }
        if (hasEntries) {
            persisted.sourceMetadata = cleaned;
        }
    }
    return persisted;
}
// =============================================================================
// Type Guards
// =============================================================================
/**
 * Check if a value is a valid message source
 *
 * @param value - Value to check
 * @returns True if value is a valid MessageSource
 */
export function isValidMessageSource(value) {
    return typeof value === 'string' && MESSAGE_SOURCE_VALUES.includes(value);
}
/**
 * Check if a value is a valid queue message status
 *
 * @param value - Value to check
 * @returns True if value is a valid QueueMessageStatus
 */
export function isValidQueueMessageStatus(value) {
    return typeof value === 'string' && QUEUE_MESSAGE_STATUSES.includes(value);
}
/**
 * Check if an object is a valid EnqueueMessageInput
 *
 * @param value - Value to check
 * @returns True if value is a valid EnqueueMessageInput
 */
export function isValidEnqueueMessageInput(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const input = value;
    if (typeof input.content !== 'string' || input.content.trim().length === 0) {
        return false;
    }
    if (typeof input.conversationId !== 'string' || input.conversationId.trim().length === 0) {
        return false;
    }
    if (!isValidMessageSource(input.source)) {
        return false;
    }
    return true;
}
/**
 * Check if an object is a valid QueuedMessage
 *
 * @param value - Value to check
 * @returns True if value is a valid QueuedMessage
 */
export function isValidQueuedMessage(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const msg = value;
    if (typeof msg.id !== 'string' || !msg.id) {
        return false;
    }
    if (typeof msg.content !== 'string') {
        return false;
    }
    if (typeof msg.conversationId !== 'string' || !msg.conversationId) {
        return false;
    }
    if (!isValidMessageSource(msg.source)) {
        return false;
    }
    if (!isValidQueueMessageStatus(msg.status)) {
        return false;
    }
    if (typeof msg.enqueuedAt !== 'string') {
        return false;
    }
    return true;
}
/**
 * Check if an object is a valid QueueStatus
 *
 * @param value - Value to check
 * @returns True if value is a valid QueueStatus
 */
export function isValidQueueStatus(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const status = value;
    if (typeof status.pendingCount !== 'number' || status.pendingCount < 0) {
        return false;
    }
    if (typeof status.isProcessing !== 'boolean') {
        return false;
    }
    if (typeof status.totalProcessed !== 'number' || status.totalProcessed < 0) {
        return false;
    }
    if (typeof status.totalFailed !== 'number' || status.totalFailed < 0) {
        return false;
    }
    if (typeof status.historyCount !== 'number' || status.historyCount < 0) {
        return false;
    }
    return true;
}
/**
 * Check if an object is a valid PersistedQueueState for safe restoration.
 *
 * @param value - Value to check
 * @returns True if value is a valid PersistedQueueState
 */
export function isValidPersistedQueueState(value) {
    if (!value || typeof value !== 'object') {
        return false;
    }
    const state = value;
    if (state.version !== PERSISTED_QUEUE_VERSION) {
        return false;
    }
    if (typeof state.savedAt !== 'string') {
        return false;
    }
    if (!Array.isArray(state.queue)) {
        return false;
    }
    // Validate each queued message
    for (const msg of state.queue) {
        if (!isValidQueuedMessage(msg)) {
            return false;
        }
    }
    // currentMessage can be null or a valid message
    if (state.currentMessage !== null && !isValidQueuedMessage(state.currentMessage)) {
        return false;
    }
    if (!Array.isArray(state.history)) {
        return false;
    }
    for (const msg of state.history) {
        if (!isValidQueuedMessage(msg)) {
            return false;
        }
    }
    if (typeof state.totalProcessed !== 'number' || state.totalProcessed < 0) {
        return false;
    }
    if (typeof state.totalFailed !== 'number' || state.totalFailed < 0) {
        return false;
    }
    return true;
}
//# sourceMappingURL=messaging.types.js.map