/**
 * PR-34 / EA-3 smoke — /api/status must never return monitor.url to
 * unauthenticated callers.
 *
 * Static check on the route handler + the schema/migration that
 * enables the displayName fallback. Definitive: runtime check would
 * require a live dev server, but the leak is purely a function of
 * what fields the route hands to NextResponse.json(), which we can
 * verify statically against the source.
 */
import './_lib';
import { ok, fail } from './_lib';
import { readFileSync, existsSync } from 'fs';
import path from 'path';

const ROOT = path.resolve(__dirname, '../..');

function read(label: string, rel: string): string {
    const abs = path.join(ROOT, rel);
    if (!existsSync(abs)) fail(`ea-3: ${label} missing`, abs);
    return readFileSync(abs, 'utf8');
}

function main(): void {
    const route = read('/api/status/route.ts', 'src/app/api/status/route.ts');
    const schema = read('schema.prisma', 'prisma/schema.prisma');
    const migration = read('EA-3 migration', 'prisma/legacy-manual-sql/ea-3-monitor-display-name.sql');
    const validations = read('monitor.schema.ts', 'src/lib/validations/monitor.schema.ts');
    const service = read('monitor.service.ts', 'src/lib/services/monitor.service.ts');

    // 1. Route handler: the monitors.map output must NOT include url.
    const mapMatch = route.match(/monitors\.map\(m\s*=>\s*\(\{([\s\S]*?)\}\)\)/);
    if (!mapMatch) fail('ea-3: monitors.map block not found', 'route shape changed');
    if (/\burl\s*:/.test(mapMatch[1])) {
        fail('ea-3: /api/status still emits url in the response', 'leak not closed');
    }
    ok('ea-3: /api/status response does not include url');

    // 2. Defence-in-depth: the prisma findMany must use `select` so url
    // never enters the JS heap.
    const findManyMatch = route.match(/prisma\.monitor\.findMany\(\{([\s\S]*?)\}\)/);
    if (!findManyMatch) fail('ea-3: prisma.monitor.findMany block not found', 'route shape changed');
    if (!/select\s*:/.test(findManyMatch[1])) {
        fail('ea-3: /api/status findMany lacks explicit `select`', 'defence-in-depth missing');
    }
    if (/\burl\s*:\s*true/.test(findManyMatch[1])) {
        fail('ea-3: /api/status findMany SELECTS url', 'unnecessary hydration');
    }
    ok('ea-3: /api/status findMany uses explicit select with no url');

    // 3. displayName fallback is wired
    if (!/displayName\s*\?\?\s*m\.name|m\.displayName/.test(route)) {
        fail('ea-3: /api/status does not use displayName fallback', 'public label missing');
    }
    ok('ea-3: /api/status renders displayName ?? name');

    // 4. Dismissive TODO comment is gone
    if (/Maybe hide this if sensitive/i.test(route)) {
        fail('ea-3: stale "Maybe hide this if sensitive" comment still present', 'fix not applied');
    }
    ok('ea-3: stale "keeping for now" comment removed');

    // 5. Schema has displayName
    if (!/displayName\s+String\?/.test(schema)) {
        fail('ea-3: Monitor.displayName missing from schema', 'migration not aligned');
    }
    ok('ea-3: Monitor.displayName declared in schema');

    // 6. Migration adds the column
    if (!/ADD COLUMN `displayName`/.test(migration)) {
        fail('ea-3: migration does not ADD COLUMN displayName', 'migration shape wrong');
    }
    ok('ea-3: migration adds Monitor.displayName');

    // 7. Zod schema accepts displayName
    if (!/displayName/.test(validations)) {
        fail('ea-3: createMonitorSchema does not accept displayName', 'API will strip the field');
    }
    ok('ea-3: createMonitorSchema accepts displayName');

    // 8. Service writes displayName on create + update
    if (!/displayName\s*:/.test(service)) {
        fail('ea-3: MonitorService.create/update does not write displayName', 'field unreachable from API');
    }
    ok('ea-3: MonitorService writes displayName on create + update');

    ok('PR-34 status-page URL leak', 'closed; displayName fallback wired end-to-end');
}

main();
