"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const sinon_1 = __importDefault(require("sinon"));
const providerHealth_1 = require("../../src/providers/chain-state/external/providerHealth");
describe('ProviderHealth', function () {
    let clock;
    beforeEach(function () {
        clock = sinon_1.default.useFakeTimers();
    });
    afterEach(function () {
        clock.restore();
    });
    it('should start available', function () {
        const ph = new providerHealth_1.ProviderHealth('test');
        (0, chai_1.expect)(ph.isAvailable()).to.equal(true);
    });
    it('should remain available below failure threshold', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 3 });
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        (0, chai_1.expect)(ph.isAvailable()).to.equal(true);
    });
    it('should become unavailable at failure threshold', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 3 });
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        (0, chai_1.expect)(ph.isAvailable()).to.equal(false);
    });
    it('should become available again after cooldown', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 2, cooldownMs: 1000 });
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        (0, chai_1.expect)(ph.isAvailable()).to.equal(false);
        clock.tick(1001);
        (0, chai_1.expect)(ph.isAvailable()).to.equal(true);
    });
    it('should go back to unavailable if retry fails', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 2, cooldownMs: 1000 });
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        clock.tick(1001);
        ph.isAvailable(); // allows retry
        ph.recordFailure(new Error('still failing'));
        (0, chai_1.expect)(ph.isAvailable()).to.equal(false);
    });
    it('should reset on success', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 3 });
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        ph.recordSuccess();
        ph.recordFailure(new Error('fail'));
        ph.recordFailure(new Error('fail'));
        // Should still be available — success reset the counter
        (0, chai_1.expect)(ph.isAvailable()).to.equal(true);
    });
    it('should use composite key with chain:network:provider', function () {
        const ph = new providerHealth_1.ProviderHealth('Alchemy', undefined, { chain: 'ETH', network: 'mainnet' });
        (0, chai_1.expect)(ph.key).to.equal('ETH:mainnet:Alchemy');
    });
    it('should report status correctly', function () {
        const ph = new providerHealth_1.ProviderHealth('test', { failureThreshold: 3 });
        ph.recordFailure(new Error('fail'));
        const status = ph.getStatus();
        (0, chai_1.expect)(status.available).to.equal(true);
        (0, chai_1.expect)(status.consecutiveFailures).to.equal(1);
    });
});
//# sourceMappingURL=providerHealth.test.js.map