import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { fail, pass, repositoryRoot } from './lib.mjs';

const expected = {
  node: '24.17.0',
  pnpm: '11.9.0',
};
const packageJson = JSON.parse(await readFile(path.join(repositoryRoot, 'package.json'), 'utf8'));
const lockfile = await readFile(path.join(repositoryRoot, 'pnpm-lock.yaml'), 'utf8');
const nodeVersion = (await readFile(path.join(repositoryRoot, '.node-version'), 'utf8')).trim();
const nvmVersion = (await readFile(path.join(repositoryRoot, '.nvmrc'), 'utf8')).trim();
const errors = [];

if (packageJson.packageManager !== `pnpm@${expected.pnpm}`) {
  errors.push(`packageManager must be pnpm@${expected.pnpm}.`);
}
if (packageJson.engines?.node !== expected.node) {
  errors.push(`package.json engines.node must be ${expected.node}.`);
}
if (packageJson.engines?.pnpm !== expected.pnpm) {
  errors.push(`package.json engines.pnpm must be ${expected.pnpm}.`);
}
if (nodeVersion !== expected.node || nvmVersion !== expected.node) {
  errors.push('.node-version and .nvmrc must match the approved Node.js runtime.');
}

const directDependencies = {
  ...(packageJson.dependencies ?? {}),
  ...(packageJson.devDependencies ?? {}),
};
const exactVersion = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
for (const [name, version] of Object.entries(directDependencies)) {
  if (typeof version !== 'string' || !exactVersion.test(version)) {
    errors.push(`${name} must use an exact direct version, received ${String(version)}.`);
    continue;
  }
  const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const lockSpecifier = new RegExp(
    `(?:^|\\n)\\s{6}['\"]?${escapedName}['\"]?:\\n\\s{8}specifier: ${escapedVersion}(?:\\n|$)`,
  );
  if (!lockSpecifier.test(lockfile)) {
    errors.push(
      `${name}@${version} is not represented by an exact importer specifier in pnpm-lock.yaml.`,
    );
  }
}

if (errors.length) fail(errors);
else {
  pass(
    `Pinned Node ${expected.node}, pnpm ${expected.pnpm}, and ${Object.keys(directDependencies).length} exact direct dependency versions match the lockfile.`,
  );
}
