/**
 * Depth-2 route smoke-import tests
 *
 * Locks in the DC-005 path fix (commit c39c80b) so future refactors can't
 * reintroduce broken require() paths in depth-2 route files.
 *
 * Background:
 *   - The DC-005 src/ refactor moved route files into depth-2 subdirectories
 *     (routes/auth/, routes/recipes/, routes/apps/, routes/arr/, routes/config/).
 *   - The path-rewrite script left 67 broken require() paths across 21 files:
 *     class A: '../../../src/...' (3 levels, goes above package root)
 *     class B: '../src/utils/...' (1 level, resolves to nonexistent routes/src/)
 *     class C: routes/apps/restore.js used 'utilities/responses' instead of 'utils/responses'
 *   - The bug shipped because NO TEST imported any depth-2 route file. Only
 *     depth-1 routes were tested.
 *
 * These tests do not exercise the routes' handler logic — that would require
 * building full app contexts per route family. They only verify:
 *   1. The module can be loaded without a MODULE_NOT_FOUND error.
 *   2. It exports a callable factory function (module.exports = function(deps){...}).
 *   3. The factory runs without throwing when given the minimum required deps.
 *
 * That alone catches ~80% of the DC-005 class: any require() with a wrong path
 * blows up at module load time, before the factory is even called. Path bugs
 * that only manifest at handler invocation time (e.g. require of a dep only
 * used inside a handler body) won't be caught — but those are rare.
 */
const fs = require('fs');
const path = require('path');
const { universalDeps } = require('./test-helpers/universal-deps');

const PKG_ROOT = path.join(__dirname, '..');
const DEPTH2_DIRS = ['apps', 'arr', 'auth', 'config', 'recipes'];

function discoverDepth2Routes() {
  const out = [];
  for (const sub of DEPTH2_DIRS) {
    const dir = path.join(PKG_ROOT, 'routes', sub);
    if (!fs.existsSync(dir)) continue;
    for (const f of fs.readdirSync(dir).filter(x => x.endsWith('.js'))) {
      out.push(path.join('routes', sub, f));
    }
  }
  return out.sort();
}

describe('Depth-2 Route Smoke Imports (locks in DC-005 path fix)', () => {
  const routes = discoverDepth2Routes();
  // routes/auth/totp.js was already fixed in the DC-006 commit (one of the
  // 21 files in the DC-005 fix batch). It was the first to be detected because
  // DC-006 added tests that imported it. Every other route in this list has
  // historically had ZERO test coverage — that's the gap this test closes.

  describe.each(routes)('module %s', (relPath) => {
    test('loads without MODULE_NOT_FOUND (catches DC-005 class A/B/C paths)', () => {
      // If any require() in this file uses '../../../src/...' (class A) or
      // '../src/utils/...' (class B) or wrong directory name (class C),
      // this require() throws and the test fails.
      expect(() => require(path.join(PKG_ROOT, relPath))).not.toThrow();
    });

    test('exports a factory function (module.exports = function(deps){...})', () => {
      const factory = require(path.join(PKG_ROOT, relPath));
      expect(typeof factory).toBe('function');
    });

    test('factory runs without throwing given minimal deps', () => {
      const factory = require(path.join(PKG_ROOT, relPath));
      // universalDeps is a Proxy that returns no-op functions for any
      // property access. So both patterns work:
      //   function({ a, b, c }) { ... }   // picks a, b, c from universalDeps
      //   function(ctx) { ctx.licenseManager.requirePremium(...) }   // works
      // Any factory destructure is satisfied. Any method call returns undefined
      // (callable no-op), so handler-invocation paths also don't crash here.
      // We are ONLY catching module-load failures and factory-call-time
      // failures — not handler-invocation behaviour.
      expect(() => factory(universalDeps)).not.toThrow();
    });
  });

  describe('Source-of-truth: no broken paths introduced', () => {
    test('no depth-2 route uses ../../../src/ (class A)', () => {
      const offenders = [];
      for (const relPath of routes) {
        const content = fs.readFileSync(path.join(PKG_ROOT, relPath), 'utf8');
        if (content.match(/require\(['"]\.\.\/\.\.\/\.\.\/src/)) offenders.push(relPath);
      }
      expect(offenders).toEqual([]);
    });

    test('no depth-2 route uses ../src/ (class B — would resolve to routes/src/)', () => {
      const offenders = [];
      for (const relPath of routes) {
        const content = fs.readFileSync(path.join(PKG_ROOT, relPath), 'utf8');
        // Match '../src/' NOT preceded by another '/' (which would be class A)
        if (content.match(/require\(['"]\.\.\/src\//)) offenders.push(relPath);
      }
      expect(offenders).toEqual([]);
    });

    test('no depth-2 route uses src/utilities/responses (class C — module lives at src/utils/responses)', () => {
      const offenders = [];
      for (const relPath of routes) {
        const content = fs.readFileSync(path.join(PKG_ROOT, relPath), 'utf8');
        if (content.match(/['"]\.\.\/\.\.\/src\/utilities\/responses['"]/)) offenders.push(relPath);
      }
      expect(offenders).toEqual([]);
    });
  });
});
