import CircuitBreaker from 'opossum';
import { createLogger } from '@4runr/shared';
const logger = createLogger('Gateway:CircuitBreaker');
const DEFAULT_OPTIONS = {
    timeout: 30000,
    errorThresholdPercentage: 50,
    resetTimeout: 60000,
    enabled: true
};
export function createCircuitBreaker(fn, serviceName, options = {}) {
    const config = { ...DEFAULT_OPTIONS, ...options };
    if (!config.enabled) {
        return {
            fire: async (...args) => fn(...args),
            open: false,
            halfOpen: false,
            closed: true
        };
    }
    const breaker = new CircuitBreaker(fn, {
        timeout: config.timeout,
        errorThresholdPercentage: config.errorThresholdPercentage,
        resetTimeout: config.resetTimeout,
        name: serviceName
    });
    breaker.on('open', () => {
        logger.warn('Circuit breaker opened', { service: serviceName });
    });
    breaker.on('halfOpen', () => {
        logger.info('Circuit breaker half-open', { service: serviceName });
    });
    breaker.on('close', () => {
        logger.info('Circuit breaker closed', { service: serviceName });
    });
    breaker.on('failure', (error) => {
        logger.error('Circuit breaker failure', {
            service: serviceName,
            error: error.message
        });
    });
    breaker.on('success', () => {
        logger.debug('Circuit breaker success', { service: serviceName });
    });
    return breaker;
}
export const openAICircuitBreaker = createCircuitBreaker(async (fn) => fn(), 'OpenAI', {
    timeout: 60000,
    errorThresholdPercentage: 50,
    resetTimeout: 120000
});
export const anthropicCircuitBreaker = createCircuitBreaker(async (fn) => fn(), 'Anthropic', {
    timeout: 60000,
    errorThresholdPercentage: 50,
    resetTimeout: 120000
});
export const httpCircuitBreaker = createCircuitBreaker(async (fn) => fn(), 'HTTP', {
    timeout: 10000,
    errorThresholdPercentage: 50,
    resetTimeout: 60000
});
export async function executeWithCircuitBreaker(breaker, fn) {
    try {
        return await breaker.fire(fn);
    }
    catch (error) {
        if (error.code === 'ECIRCUITOPEN') {
            throw new Error(`Service temporarily unavailable (circuit open): ${error.message}`);
        }
        throw error;
    }
}
//# sourceMappingURL=circuit-breaker.js.map