#!/usr/bin/env node
/**
 * no-undef over the SERVER-side modules: routes/, services/, db/, middleware/.
 *
 * WHY
 * ---
 * `routes/ebs-deep-reports.js` used COOKIE_NAME and verifyToken at four call
 * sites and imported neither. Both are real identifiers — they live in
 * middleware/auth.js — so the file parsed, booted, served every other route, and
 * threw ReferenceError only when someone actually opened a saved Deep EBS report:
 *
 *     [ebs-deep-reports] Report fetch error: ReferenceError: COOKIE_NAME is not defined
 *
 * The user-visible symptom was "no report found" on a report that had just been
 * created and was sitting in the database. The report view and the PDF export had
 * never worked for a non-demo report.
 *
 * Nothing caught it. `node --check` sees parse errors only; boot-smoke loads every
 * module, which proves the file evaluates, not that its code paths resolve; and
 * scripts/ci/lint-inline-scripts.js deliberately covers inline <script> blocks in
 * public/*.html and nothing else. This closes the same hole on the server side.
 *
 * Exits 2 (not 1) if it finds no files to lint, so a broken glob cannot pass as a
 * clean run.
 */
const path = require('path');
const { ESLint } = require('eslint');

const ROOT = path.resolve(__dirname, '..', '..');
const DIRS = ['routes', 'services', 'db', 'middleware', 'lib', 'config'];

(async () => {
  const eslint = new ESLint({
    overrideConfigFile: true,
    overrideConfig: {
      languageOptions: {
        ecmaVersion: 2022,
        sourceType: 'commonjs',
        globals: {
          require: 'readonly', module: 'writable', exports: 'writable',
          __dirname: 'readonly', __filename: 'readonly', process: 'readonly',
          console: 'readonly', Buffer: 'readonly', URL: 'readonly',
          URLSearchParams: 'readonly', TextEncoder: 'readonly', TextDecoder: 'readonly',
          setTimeout: 'readonly', clearTimeout: 'readonly',
          setInterval: 'readonly', clearInterval: 'readonly', setImmediate: 'readonly',
          fetch: 'readonly', AbortController: 'readonly', AbortSignal: 'readonly',
          structuredClone: 'readonly', global: 'readonly', globalThis: 'readonly',
          performance: 'readonly', crypto: 'readonly', queueMicrotask: 'readonly',
          Blob: 'readonly', FormData: 'readonly', Headers: 'readonly',
          Request: 'readonly', Response: 'readonly', ReadableStream: 'readonly',
        },
      },
      rules: { 'no-undef': 'error' },
    },
  });

  const targets = DIRS.map(d => path.join(ROOT, d, '**/*.js'));
  let results;
  try {
    results = await eslint.lintFiles(targets);
  } catch (err) {
    console.error('FATAL: lint could not run — ' + err.message);
    process.exit(2);
  }

  if (!results.length) {
    console.error('FATAL: matched 0 files — the glob is broken, not the code');
    process.exit(2);
  }

  const problems = [];
  for (const r of results) {
    for (const m of r.messages) {
      if (m.ruleId === 'no-undef') {
        problems.push({ file: path.relative(ROOT, r.filePath), line: m.line, msg: m.message });
      }
    }
  }

  console.log(`Linted ${results.length} server-side JS files across ${DIRS.join(', ')}.`);
  if (!problems.length) {
    console.log('no-undef: clean.');
    process.exit(0);
  }

  console.error(`\n${problems.length} undefined-reference problem(s):\n`);
  let last = null;
  for (const p of problems) {
    if (p.file !== last) { console.error(`  ${p.file}`); last = p.file; }
    console.error(`    ${path.basename(p.file)}:${p.line}  ${p.msg}`);
  }
  console.error('\nAn identifier that exists in ANOTHER module still throws here.');
  console.error('This is the COOKIE_NAME bug: it parses, it boots, it fails only when');
  console.error('the code path actually runs. Import it — do not add a global.');
  process.exit(1);
})();
