#!/usr/bin/env node
/**
 * scripts/ci/boot-smoke.js — assert every route and service module is require()-able.
 *
 * Run twice by .github/workflows/boot-smoke.yml: once with OPENAI_API_KEY set and
 * once with it empty. Both must pass.
 *
 * WHY: on 2026-08-05 the app could not boot at all without OPENAI_API_KEY. The
 * OpenAI SDK constructor throws on a missing key (even when apiKey is passed
 * explicitly as undefined), and server.js plus routes/addm.js, routes/fndload.js
 * and routes/proxy-self-test.js each built a client at MODULE SCOPE — so require()
 * threw before any guard could run, and server.js's own AI_ENABLED check was
 * unreachable dead code. AI is documented as OPTIONAL (self-hosted installs run
 * health checks with an AI placeholder), so the no-key path is a shipping
 * configuration, not a corner case.
 *
 * The rule this encodes: module scope is for wiring, not for constructing clients
 * that can fail. Anything that can throw belongs inside a handler or behind a lazy
 * getter (see lib/openai-client.js).
 *
 * Deliberately does NOT provide a database. Modules must be importable without one;
 * that is itself the property under test.
 *
 * Usage: node scripts/ci/boot-smoke.js
 * Exits 0 if every module loads, 1 otherwise (with a per-module error listing).
 */

'use strict';

const fs = require('fs');
const path = require('path');

const ROOT = path.join(__dirname, '..', '..');
const DIRS = ['routes', 'services'];

const hasKey = Boolean(process.env.OPENAI_API_KEY);
console.log(`boot-smoke: OPENAI_API_KEY ${hasKey ? 'SET' : 'UNSET'}\n`);

const failures = [];
let loaded = 0;

for (const dir of DIRS) {
  const abs = path.join(ROOT, dir);
  if (!fs.existsSync(abs)) continue;

  for (const file of fs.readdirSync(abs).filter((f) => f.endsWith('.js')).sort()) {
    const rel = `${dir}/${file}`;
    try {
      require(path.join(abs, file));
      loaded++;
    } catch (err) {
      failures.push({ rel, message: (err && err.message ? err.message : String(err)).split('\n')[0] });
    }
  }
}

console.log(`loaded ${loaded} module(s), ${failures.length} failure(s)`);

if (failures.length) {
  console.error('');
  for (const f of failures) {
    // GitHub Actions annotation — surfaces inline on the PR diff.
    console.error(`::error file=${f.rel}::fails to load at require() time — ${f.message}`);
  }
  console.error(
    '\nA module must be require()-able with a minimal environment. Move anything ' +
    'that can throw (API clients, connections, credential reads) out of module scope ' +
    'and behind a lazy getter — see lib/openai-client.js.',
  );
  process.exit(1);
}

console.log('OK — every route and service module loads.');
process.exit(0);
