// The version is stated in several places that a release has to keep in step.
// The one in the header was hard-coded and drifted: the application advertised
// v5.6.0 while running 5.7.1. Anything a person has to remember at release time
// eventually gets forgotten, so these assertions do the remembering.

import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';

const read = (rel) => readFileSync(new URL(`../${rel}`, import.meta.url), 'utf8');

const pkg = JSON.parse(read('package.json'));
const version = pkg.version;
assert.match(version, /^\d+\.\d+\.\d+$/, 'package.json must carry a plain semver version');

// package.json is the single source of truth. The header must derive from it
// rather than restate it, so no release step is needed to keep them together.
{
    const header = read('src/components/ui/Header.jsx');
    assert.match(
        header,
        /import\s*\{\s*version[^}]*\}\s*from\s*['"][^'"]*package\.json['"]/,
        'the header must import the version from package.json'
    );
    assert.equal(
        /['"]v\d+\.\d+\.\d+['"]/.test(header),
        false,
        'the header must not contain a hard-coded version literal'
    );
}

// meta.json drives the update check and is regenerated by the build. If it is
// behind, the build was not re-run before committing and clients will not be
// told an update exists.
{
    const meta = JSON.parse(read('meta.json'));
    assert.equal(
        meta.appVersion, version,
        'meta.json is stale: run `npm run build` before committing a version bump'
    );
}

// The README badge and the changelog are read by people deciding whether to
// update, so a mismatch there is a mismatch in what we are telling them.
{
    const readme = read('README.md');
    assert.ok(
        readme.includes(`version-${version}-`),
        `the README version badge must show ${version}`
    );

    const changelog = read('CHANGELOG.md');
    const firstEntry = changelog.split('\n').find((line) => line.startsWith('## v'));
    assert.ok(
        firstEntry && firstEntry.startsWith(`## v${version}`),
        `the newest changelog entry must be v${version}, found: ${firstEntry}`
    );
}

// Documentation quotes the release it describes.
{
    const crypto = read('doc/CRYPTOGRAPHY.md');
    assert.ok(
        crypto.includes(version),
        `doc/CRYPTOGRAPHY.md must reference the current release (${version})`
    );
}

console.log('version-consistency.test.mjs: all assertions passed');
