import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import semver from 'semver';

const repositoryRoot = dirname(fileURLToPath(new URL('../package.json', import.meta.url)));

function readManifest(path) {
  return JSON.parse(readFileSync(path, 'utf8'));
}

function fail(headline, problems) {
  console.error([headline, ...problems.map((problem) => `- ${problem}`)].join('\n'));
  process.exit(1);
}

const rootManifest = readManifest(join(repositoryRoot, 'package.json'));
const rootRange = rootManifest.engines?.node;
const rootMinimum = rootRange ? semver.minVersion(rootRange) : null;
if (!rootRange || rootMinimum === null) {
  fail('The root Node engine contract is invalid:', [
    `package.json engines.node must be a valid semver range, got ${JSON.stringify(rootRange)}.`,
  ]);
}

const failures = [];
let constrainedDependencies = 0;

for (const dependency of Object.keys(rootManifest.dependencies ?? {}).sort()) {
  const manifestPath = join(
    repositoryRoot,
    'node_modules',
    ...dependency.split('/'),
    'package.json',
  );
  let manifest;
  try {
    manifest = readManifest(manifestPath);
  } catch (error) {
    failures.push(
      `cannot read installed manifest for ${dependency} at ${manifestPath}: ${String(error)}. ` +
        'Run pnpm install before this check.',
    );
    continue;
  }

  const dependencyRange = manifest.engines?.node;
  if (!dependencyRange) continue;
  constrainedDependencies += 1;
  const dependencyMinimum = semver.minVersion(dependencyRange);
  if (dependencyMinimum === null) {
    failures.push(
      `${dependency} declares an invalid engines.node range: ${JSON.stringify(dependencyRange)}.`,
    );
    continue;
  }
  if (semver.lt(rootMinimum, dependencyMinimum)) {
    failures.push(
      `root engines.node ${JSON.stringify(rootRange)} starts at ${rootMinimum.version}, below ` +
        `${dependency}@${manifest.version} engines.node ${JSON.stringify(dependencyRange)} ` +
        `(minimum ${dependencyMinimum.version}).`,
    );
  }
}

if (failures.length > 0) {
  fail('The root Node engine minimum is below its direct production dependencies:', failures);
}

console.log(
  `Node engine contract passed: root minimum ${rootMinimum.version} satisfies ` +
    `${constrainedDependencies} engine-constrained direct production dependencies.`,
);