/**
 * App startup require-graph smoke test (DC-020 regression guard)
 *
 * WHY THIS EXISTS:
 *   The `refactor(desloppify)` commit deleted `license-keygen.js` thinking it was
 *   stale dev-root noise. It is actually required by `src/managers/license-manager.js`
 *   (`require('./license-keygen')`). The deletion put the production `dashcaddy-api`
 *   container in a crash-restart loop (MODULE_NOT_FOUND from /app/src/app.js). A second,
 *   masked bug had the same effect from the entry point: server.js used `require('./state-manager')`
 *   which from /app/server.js resolves to /app/state-manager.js (does not exist) instead of
 *   `./src/managers/state-manager`. The full Jest suite passed anyway because NO test ever
 *   executed the real production require graph — every "app" test read src/app.js as a
 *   string or rebuilt a minimal Express app with copied handlers, and server.js was never
 *   loaded at all (requiring it starts the HTTP server + timers, which would leak workers).
 *
 *   This test closes that gap two ways:
 *     1. Execute the real src/app.js require graph (catches deleted-module regressions).
 *     2. Statically verify EVERY relative require in server.js resolves to a real file
 *        (catches entry-point path bugs like the ./state-manager regression, without starting
 *        the server). server.js cannot be require()'d directly because its top-level IIFE
 *        binds port 3001 and starts interval-based feature modules.
 */
const fs = require('fs');
const path = require('path');

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

describe('app startup require-graph smoke', () => {
  it('src/app.js and its entire require graph load without throwing', () => {
    expect(() => require(path.join(ROOT, 'src', 'app'))).not.toThrow();
  });

  it('createApp is exported as a function', () => {
    const mod = require(path.join(ROOT, 'src', 'app'));
    expect(typeof mod.createApp).toBe('function');
  });

  it('every relative require() in server.js resolves to a real module', () => {
    // server.js is the production entry point (Dockerfile CMD ["node","server.js"]).
    // We statically check its require graph because require()-ing it at test time
    // starts the HTTP server and interval-based modules (would leak the worker).
    const serverFile = path.join(ROOT, 'server.js');
    const src = fs.readFileSync(serverFile, 'utf8')
      // strip block + line comments so example requires in docstrings don't trip us up
      .replace(/\/\*[\s\S]*?\*\//g, '')
      .replace(/(^|[^:\\])\/\/.*$/gm, '$1');

    const requireRe = /require\(\s*['"]([^'"]+)['"]\s*\)/g;
    const unresolved = [];
    let match;
    while ((match = requireRe.exec(src))) {
      const spec = match[1];
      if (!spec.startsWith('.')) continue; // only relative specs are path-bug-prone
      const base = path.resolve(path.dirname(serverFile), spec);
      const ok = fs.existsSync(base + '.js') ||
                 fs.existsSync(base + '.json') ||
                 fs.existsSync(path.join(base, 'index.js'));
      if (!ok) unresolved.push(spec);
    }
    expect(unresolved).toEqual([]);
  });
});
