/**
 * Base Alert Channel
 *
 * Abstract base class for all alert channels providing common functionality:
 * - Exponential backoff retry logic
 * - Error handling and logging
 * - Delivery result formatting
 *
 * @packageDocumentation
 * @module security/alerting/channels/base
 */
import { createLogger } from '../../../common/logger.js';
// =============================================================================
// Constants
// =============================================================================
const DEFAULT_TIMEOUT = 10000;
const DEFAULT_MAX_RETRIES = 3;
const DEFAULT_MAX_BACKOFF_DELAY = 10000;
const DEFAULT_BASE_BACKOFF_DELAY = 1000;
// =============================================================================
// BaseAlertChannel Class
// =============================================================================
/**
 * Abstract base class for all alert channels
 *
 * Provides common retry logic, error handling, and result formatting.
 * Subclasses must implement sendInternal() with channel-specific logic.
 */
export class BaseAlertChannel {
    logger;
    timeout;
    maxRetries;
    maxBackoffDelay;
    baseBackoffDelay;
    constructor(config = {}) {
        this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
        this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
        this.maxBackoffDelay = config.maxBackoffDelay ?? DEFAULT_MAX_BACKOFF_DELAY;
        this.baseBackoffDelay = config.baseBackoffDelay ?? DEFAULT_BASE_BACKOFF_DELAY;
        // Logger will be initialized with component name in subclass constructor
        this.logger = createLogger({ component: 'base-alert-channel' });
    }
    /**
     * Send an alert through this channel with retry logic
     */
    async send(alert) {
        const startTime = Date.now();
        let retryCount = 0;
        let lastError = null;
        while (retryCount <= this.maxRetries) {
            try {
                const result = await this.sendInternal(alert);
                this.logger.info({
                    alertId: alert.id,
                    messageId: result.messageId,
                    severity: alert.severity,
                    retryCount,
                    durationMs: Date.now() - startTime,
                }, `Alert sent to ${this.channelName}`);
                return this.createSuccessResult(result.messageId, retryCount);
            }
            catch (error) {
                lastError = error instanceof Error ? error : new Error(String(error));
                retryCount++;
                if (retryCount <= this.maxRetries) {
                    const delay = this.calculateBackoff(retryCount);
                    this.logger.warn({
                        alertId: alert.id,
                        error: lastError.message,
                        retryCount,
                        nextRetryIn: delay,
                    }, `Retrying ${this.channelName} request`);
                    await this.sleep(delay);
                }
            }
        }
        this.logger.error({
            alertId: alert.id,
            error: lastError?.message,
            retryCount,
        }, `Failed to send alert to ${this.channelName}`);
        return this.createFailureResult(lastError?.message ?? 'Unknown error', retryCount);
    }
    /**
     * Calculate exponential backoff delay
     */
    calculateBackoff(attempt) {
        const delay = this.baseBackoffDelay * Math.pow(2, attempt - 1);
        return Math.min(delay, this.maxBackoffDelay);
    }
    /**
     * Sleep for specified milliseconds
     */
    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    /**
     * Create a success delivery result
     */
    createSuccessResult(messageId, retryCount = 0) {
        return {
            channel: this.channelType,
            success: true,
            messageId,
            timestamp: new Date(),
            retryCount,
        };
    }
    /**
     * Create a failure delivery result
     */
    createFailureResult(error, retryCount = 0) {
        return {
            channel: this.channelType,
            success: false,
            error,
            timestamp: new Date(),
            retryCount,
        };
    }
    /**
     * Create logger for a specific component
     */
    createChannelLogger(component) {
        return createLogger({ component });
    }
}
//# sourceMappingURL=base.js.map