/**
 * audit3-followup (2026-05-30): the cPanel/Passenger deploy must sync the DB
 * schema BEFORE restarting the app, and fail closed.
 *
 * Background: Passenger boots server.js directly and (unlike
 * docker-entrypoint.sh) runs no migrations. A bare `git pull` shipped code
 * that SELECTed User.passwordChangedAt before its migration applied → every
 * login returned NextAuth AccessDenied. deploy.sh closes that gap.
 *
 * This smoke statically asserts deploy.sh:
 *   1. exists at the repo root,
 *   2. fails closed (`set -euo pipefail`),
 *   3. runs `prisma migrate deploy`,
 *   4. does so BEFORE the Passenger restart (touch tmp/restart.txt) — so a
 *      failed migration aborts the deploy with old code still serving.
 */
import './_lib';
import { ok, fail } from './_lib';
import { existsSync, readFileSync } from 'fs';
import path from 'path';

const ROOT = path.resolve(__dirname, '../..');
const DEPLOY = path.join(ROOT, 'deploy.sh');

function main(): void {
    if (!existsSync(DEPLOY)) {
        fail('audit3-migrate-deploy-guard: deploy.sh present', `not found at ${DEPLOY}`);
    }
    const sh = readFileSync(DEPLOY, 'utf8');

    if (!/set\s+-euo\s+pipefail/.test(sh)) {
        fail('audit3-migrate-deploy-guard: deploy.sh fails closed', 'missing `set -euo pipefail`');
    }
    ok('audit3-migrate-deploy-guard: deploy.sh fails closed (set -euo pipefail)');

    const migrateIdx = sh.indexOf('prisma migrate deploy');
    if (migrateIdx === -1) {
        fail('audit3-migrate-deploy-guard: deploy.sh runs prisma migrate deploy', 'no `prisma migrate deploy` line');
    }
    ok('audit3-migrate-deploy-guard: deploy.sh runs prisma migrate deploy');

    const restartMatch = sh.match(/touch\s+tmp\/restart\.txt/);
    if (!restartMatch || restartMatch.index === undefined) {
        fail('audit3-migrate-deploy-guard: deploy.sh restarts Passenger', 'no `touch tmp/restart.txt` step');
    }
    if (migrateIdx > restartMatch.index) {
        fail(
            'audit3-migrate-deploy-guard: migrate deploy precedes restart',
            'schema must be synced BEFORE the app restarts (fail-closed invariant)',
        );
    }
    ok('audit3-migrate-deploy-guard: migrate deploy runs before the Passenger restart');

    // One-command deploy: it pulls latest code, and the pull must precede the
    // build (so we build/migrate the new code, not the stale checkout).
    const pullIdx = sh.search(/git\s+pull[^\n]*--ff-only/);
    if (pullIdx === -1) {
        fail('audit3-migrate-deploy-guard: deploy.sh pulls latest code (ff-only)', 'no `git pull --ff-only` step');
    }
    const buildIdx = sh.indexOf('npm run build');
    if (buildIdx === -1 || pullIdx > buildIdx) {
        fail('audit3-migrate-deploy-guard: git pull precedes the build', 'code must be synced BEFORE building');
    }
    ok('audit3-migrate-deploy-guard: git pull (ff-only) runs before the build');

    ok('audit3-migrate-deploy-guard', 'cPanel deploy path pulls + migrates before restart, fail-closed');
}

main();
