// Quality Intelligence circuit breaker (Epic #270, Issue #279).
//
// Pure half-open state machine. The dispatcher records each model call outcome via
// `transitionOn` and consults `state` to decide whether to attempt or skip a call. State is
// immutable; every transition returns a new value. Thresholds are configurable but default
// to a frozen constant tuned for QI workloads.
export const DEFAULT_QUALITY_INTELLIGENCE_CIRCUIT_BREAKER_CONFIG = Object.freeze({
    failureThreshold: 4,
    cooldownMs: 30_000,
    halfOpenProbes: 1,
});
export function createCircuitBreakerState() {
    return Object.freeze({
        state: "closed",
        consecutiveFailures: 0,
        openedAtMs: null,
    });
}
function onSuccess() {
    return Object.freeze({
        state: "closed",
        consecutiveFailures: 0,
        openedAtMs: null,
    });
}
function onFailure(state, config, nowMs) {
    const nextFailures = state.consecutiveFailures + 1;
    if (nextFailures >= config.failureThreshold) {
        return Object.freeze({
            state: "open",
            consecutiveFailures: nextFailures,
            openedAtMs: nowMs,
        });
    }
    return Object.freeze({
        state: state.state === "half-open" ? "open" : state.state,
        consecutiveFailures: nextFailures,
        openedAtMs: state.state === "half-open" ? nowMs : state.openedAtMs,
    });
}
function onProbe(state) {
    if (state.state === "open") {
        return Object.freeze({
            state: "half-open",
            consecutiveFailures: state.consecutiveFailures,
            openedAtMs: state.openedAtMs,
        });
    }
    return state;
}
function onTick(state, config, nowMs) {
    if (state.state !== "open" || state.openedAtMs === null) {
        return state;
    }
    if (nowMs - state.openedAtMs >= config.cooldownMs) {
        return Object.freeze({
            state: "half-open",
            consecutiveFailures: state.consecutiveFailures,
            openedAtMs: state.openedAtMs,
        });
    }
    return state;
}
export function transitionOn(state, event, config = DEFAULT_QUALITY_INTELLIGENCE_CIRCUIT_BREAKER_CONFIG, nowMs = 0) {
    switch (event.kind) {
        case "success":
            return onSuccess();
        case "failure":
            return onFailure(state, config, nowMs);
        case "probe":
            return onProbe(state);
        case "tick":
            return onTick(state, config, event.nowMs);
    }
}
export function shouldAttempt(state) {
    return state.state !== "open";
}
