import { shouldMarkHeartbeatDown } from '../heartbeat-sweeper';

const t = (iso: string) => new Date(iso);

describe('shouldMarkHeartbeatDown', () => {
    const baseMonitor = { intervalSeconds: 3600 }; // hourly cron

    it('skips when lastPingAt is null', () => {
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt: null },
            null,
            t('2026-05-22T12:00:00Z'),
        )).toBe(false);
    });

    it('skips when last ping is fresh (within interval)', () => {
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt: t('2026-05-22T11:30:00Z') },
            null,
            t('2026-05-22T12:00:00Z'),
        )).toBe(false);
    });

    it('skips when last ping is just slightly late (within stale factor window)', () => {
        // 3600s × 1.5 = 5400s = 90 min. 80 min ago is still inside the window.
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt: t('2026-05-22T10:40:00Z') },
            null,
            t('2026-05-22T12:00:00Z'),
        )).toBe(false);
    });

    it('marks down when last ping exceeds intervalSeconds × stale factor', () => {
        // Last ping 95 min ago, hourly threshold = 90 min.
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt: t('2026-05-22T10:25:00Z') },
            null,
            t('2026-05-22T12:00:00Z'),
        )).toBe(true);
    });

    it('skips when already marked down by a prior sweep this cycle', () => {
        const lastPingAt = t('2026-05-22T10:00:00Z');
        const latest = { id: 5, status: 'down', createdAt: t('2026-05-22T11:30:00Z') };
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt },
            latest,
            t('2026-05-22T12:00:00Z'),
        )).toBe(false);
    });

    it('still marks down when latest heartbeat is up (recovery from earlier outage)', () => {
        const lastPingAt = t('2026-05-22T10:00:00Z');
        const latest = { id: 5, status: 'up', createdAt: t('2026-05-22T10:00:00Z') };
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt },
            latest,
            t('2026-05-22T12:00:00Z'),
        )).toBe(true);
    });

    it('still marks down when prior down is older than lastPingAt (different cycle)', () => {
        // Old down from yesterday; today\'s ping arrived, then another miss.
        const lastPingAt = t('2026-05-22T08:00:00Z');
        const latest = { id: 5, status: 'down', createdAt: t('2026-05-21T20:00:00Z') };
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt },
            latest,
            t('2026-05-22T12:00:00Z'),
        )).toBe(true);
    });

    it('respects a custom stale factor', () => {
        // staleFactor=2.0 means 2 hours of grace; 95 min ago no longer stale.
        expect(shouldMarkHeartbeatDown(
            { ...baseMonitor, lastPingAt: t('2026-05-22T10:25:00Z') },
            null,
            t('2026-05-22T12:00:00Z'),
            2.0,
        )).toBe(false);
    });
});
