/**
 * PR-26 smoke — escalation service schedule / cancel / tick contract.
 *
 * Run: npx tsx scripts/smoke/pr26-escalation.ts
 */
import './_lib';
import { ok, fail } from './_lib';
import { EscalationService } from '../../src/lib/services/escalation.service';

// Stub the dispatcher module so tick() doesn't re-enter the full pipeline.
const dispatcherMod = require('../../src/lib/notification-system') as { NotificationDispatcher: { emit: (...args: unknown[]) => Promise<void> } };
dispatcherMod.NotificationDispatcher.emit = async () => undefined;

async function main(): Promise<void> {
    const fixedNow = new Date('2026-05-22T18:00:00Z');

    // schedule writes a row with the right scheduledFor
    let createdRow: { data: { scheduledFor: Date; payload: string } } | null = null;
    const prismaStub: Record<string, unknown> = {
        pendingEscalation: {
            create: async (args: typeof createdRow) => {
                createdRow = args;
                return { id: 1 };
            },
            findMany: async () => [],
            delete: async () => undefined,
            deleteMany: async () => ({ count: 0 }),
        },
        heartbeat: { findFirst: async () => null },
        statusIncident: { findUnique: async () => null },
    };
    const svc = new EscalationService(prismaStub as never, () => fixedNow);
    const id = await svc.schedule({
        ruleId: 1,
        eventKey: 'monitor_down:42:0',
        event: 'monitor_down',
        payload: { monitorId: 42 },
        delayMinutes: 15,
        monitorId: 42,
    });
    if (id !== 1) fail('PR-26 schedule', 'schedule should return the created row id');
    if (!createdRow) fail('PR-26 schedule', 'schedule did not call prisma.create');
    const diff = (createdRow!.data.scheduledFor.getTime() - fixedNow.getTime()) / 60_000;
    if (diff !== 15) fail('PR-26 schedule', `expected 15 min delay, got ${diff}`);
    ok('schedule writes a row with scheduledFor = now + delayMinutes');

    // tick dispatches when monitor still down
    const prismaStub2: Record<string, unknown> = {
        pendingEscalation: {
            findMany: async () => [
                { id: 5, event: 'monitor_down', monitorId: 42, incidentId: null, payload: JSON.stringify({ monitorId: 42 }) },
            ],
            delete: async () => undefined,
        },
        heartbeat: { findFirst: async () => ({ status: 'down' }) },
        statusIncident: { findUnique: async () => null },
    };
    const svc2 = new EscalationService(prismaStub2 as never, () => fixedNow);
    const r = await svc2.tick(50);
    if (r.dispatched !== 1) fail('PR-26 dispatch', `expected 1 dispatched, got ${r.dispatched}`);
    if (r.cancelled !== 0) fail('PR-26 dispatch', `expected 0 cancelled, got ${r.cancelled}`);
    ok('tick dispatches when monitor still down');

    // tick cancels when monitor recovered
    const prismaStub3: Record<string, unknown> = {
        pendingEscalation: {
            findMany: async () => [
                { id: 5, event: 'monitor_down', monitorId: 42, incidentId: null, payload: JSON.stringify({ monitorId: 42 }) },
            ],
            delete: async () => undefined,
        },
        heartbeat: { findFirst: async () => ({ status: 'up' }) },
        statusIncident: { findUnique: async () => null },
    };
    const svc3 = new EscalationService(prismaStub3 as never, () => fixedNow);
    const r2 = await svc3.tick(50);
    if (r2.cancelled !== 1) fail('PR-26 cancel', `expected 1 cancelled, got ${r2.cancelled}`);
    if (r2.dispatched !== 0) fail('PR-26 cancel', `expected 0 dispatched, got ${r2.dispatched}`);
    ok('tick cancels when monitor has recovered');

    ok('PR-26 escalation smoke', 'schedule + tick + cancel contract holds');
}

main().catch((e) => fail('PR-26 crashed', String(e)));
