'use strict';

// Shared pipeline-freshness tier (Ship A + design-train M1b). The desktop
// HeartbeatBar and the mobile app-bar clock BOTH key off this — one source, so
// mobile can never silently disagree with desktop about staleness.

const { freshnessTier, DEFAULT_EXPECTED_S } = require('../../web/src/lib/freshness');

const S = 1000;
const now = 1_000_000_000_000;

describe('freshnessTier', () => {
  test('calm when the heartbeat is recent (< 1.5× expected)', () => {
    const r = freshnessTier(now - 1000 * S, 1200, now); // 1000s elapsed, expected 1200 → 0.83×
    expect(r.tier).toBe('normal');
    expect(r.elapsedMs).toBe(1000 * S);
  });

  test('amber at ≥ 1.5× expected (the reaction begins)', () => {
    const r = freshnessTier(now - 1800 * S, 1200, now); // 1800/1200 = 1.5×
    expect(r.tier).toBe('amber');
  });

  test('stale (red) at ≥ 3× expected — never silently stale', () => {
    const r = freshnessTier(now - 3600 * S, 1200, now); // 3600/1200 = 3×
    expect(r.tier).toBe('stale');
  });

  test('absent/NaN heartbeat is calm, not a false STALE', () => {
    expect(freshnessTier(NaN, 1200, now).tier).toBe('normal');
    expect(freshnessTier(NaN, 1200, now).elapsedMs).toBeNull();
  });

  test('non-positive expected falls back to the default 5h gap', () => {
    // 4h elapsed vs the 5h (18000s) default → still under 1.5× → calm
    const r = freshnessTier(now - 4 * 3600 * S, 0, now);
    expect(DEFAULT_EXPECTED_S).toBe(18000);
    expect(r.tier).toBe('normal');
  });

  test('future/negative elapsed clamps to 0 (calm), never a negative age', () => {
    const r = freshnessTier(now + 5000 * S, 1200, now);
    expect(r.elapsedMs).toBe(0);
    expect(r.tier).toBe('normal');
  });
});
