/**
 * Run: node stall_recovery.test.js
 */
const assert = require("assert");
const { createStallRecovery } = require("./stall_recovery");

let passed = 0;
let failed = 0;

function test(name, fn) {
  try {
    fn();
    passed++;
    console.log(`ok ${name}`);
  } catch (e) {
    failed++;
    console.error(`FAIL ${name}:`, e.message);
  }
}

test("first missed slot at a tip does not park", () => {
  const sr = createStallRecovery({ missedBeforePark: 2 });
  sr.recordTipAdvance(100);
  const r = sr.onMissedSlot("SRMD_A", 100);
  assert.strictEqual(r.action, "continue");
  assert.strictEqual(r.consecutiveMisses, 1);
});

test("second consecutive miss at same tip requests park", () => {
  const sr = createStallRecovery({ missedBeforePark: 2 });
  sr.recordTipAdvance(9762);
  sr.onMissedSlot("SRMD_A", 9762);
  const r = sr.onMissedSlot("SRMD_A", 9762);
  assert.strictEqual(r.action, "park");
  assert.strictEqual(r.producer, "SRMD_A");
  assert.strictEqual(r.consecutiveMisses, 2);
  assert.strictEqual(r.tipHeight, 9762);
});

test("tip advance clears miss streak", () => {
  const sr = createStallRecovery({ missedBeforePark: 2 });
  sr.recordTipAdvance(10);
  sr.onMissedSlot("SRMD_A", 10);
  sr.recordTipAdvance(11);
  const r = sr.onMissedSlot("SRMD_A", 11);
  assert.strictEqual(r.action, "continue");
  assert.strictEqual(r.consecutiveMisses, 1);
});

test("successful producer streak resets after tip moves", () => {
  const sr = createStallRecovery({ missedBeforePark: 2 });
  sr.recordTipAdvance(5);
  sr.onMissedSlot("SRMD_A", 5);
  sr.onMissedSlot("SRMD_A", 5);
  sr.recordTipAdvance(6);
  const r = sr.onMissedSlot("SRMD_A", 6);
  assert.strictEqual(r.action, "continue");
  assert.strictEqual(r.consecutiveMisses, 1);
});

test("threshold of 1 parks on first miss", () => {
  const sr = createStallRecovery({ missedBeforePark: 1 });
  sr.recordTipAdvance(1);
  const r = sr.onMissedSlot("SRMD_B", 1);
  assert.strictEqual(r.action, "park");
});

console.log(`\n${passed} passed, ${failed} failed`);
if (failed) process.exit(1);
