/**
 * PR-B.2 smoke — confirmed-state evaluator with up-side hysteresis.
 *
 * The pure decision function `evaluateConfirmedState` is what stops
 * recovery flap-spam. The engine still owns side effects; this smoke
 * exercises the four operationally interesting transitions:
 *   - cold start (first up sets state)
 *   - going down (requires N consecutive downs)
 *   - going up from down (NEW: requires N consecutive ups)
 *   - flap (up→down→up inside the recovery window stays in down)
 *
 * Run: npx tsx scripts/smoke/prb-2-up-hysteresis.ts
 */
import './_lib';
import { ok, fail } from './_lib';
import { evaluateConfirmedState } from '../../src/lib/monitor-state';

const up = { status: 'up' };
const down = { status: 'down' };

function eq(actual: { prev: string; next: string }, expected: { prev: string; next: string }, label: string) {
    if (actual.prev !== expected.prev || actual.next !== expected.next) {
        fail(label, `expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
    }
}

function main(): void {
    // Cold start: first up resolves to up.
    eq(evaluateConfirmedState([], up, 3, 2), { prev: 'unknown', next: 'up' }, 'PR-B.2 cold-start up');
    ok('cold start: first up resolves to up');

    // 3 consecutive downs trip the down threshold.
    eq(evaluateConfirmedState([down, down], down, 3, 2), { prev: 'up', next: 'down' }, 'PR-B.2 going down');
    ok('3 consecutive downs trip the down threshold');

    // The fix: a single up after confirmed-down does NOT flip yet.
    eq(evaluateConfirmedState([down, down, down], up, 3, 2), { prev: 'down', next: 'down' }, 'PR-B.2 lone up');
    ok('lone up after confirmed-down stays in down (no premature monitor.up)');

    // Two consecutive ups DO clear.
    eq(evaluateConfirmedState([up, down, down, down], up, 3, 2), { prev: 'down', next: 'up' }, 'PR-B.2 two ups clear');
    ok('two consecutive ups clear to up (monitor.up fires here, not on the lone up)');

    // Flap inside the recovery window stays in down.
    eq(evaluateConfirmedState([down, up, down, down, down], up, 3, 2), { prev: 'down', next: 'down' }, 'PR-B.2 flap');
    ok('up→down→up flap inside the recovery window stays in down');

    // requiredUps=1 reproduces the old behavior (one-up clears).
    eq(evaluateConfirmedState([down, down, down], up, 3, 1), { prev: 'down', next: 'up' }, 'PR-B.2 requiredUps=1');
    ok('requiredUps=1 reproduces the pre-PR-B.2 single-up clearing');

    ok('PR-B.2 up-hysteresis smoke', 'recovery flap-spam closed');
}

main();
