/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import assert from 'node:assert/strict';
import childProcess, { execFileSync } from 'node:child_process';
import { syncBuiltinESMExports } from 'node:module';
import { createHash } from 'node:crypto';
import { copyFile, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { previewVersion, releaseNativeCli } from './release-cli.mjs';
import {
  previewTargets,
  publishPreviewRelease,
  readNativePreviewRelease,
  readPreviewRelease,
} from './publish-cli.mjs';
import { packLauncher } from './pack-launcher.mjs';

test('prepared release binds its source and recovers partial publication and missing tags', async (t) => {
  const stage = await mkdtemp(join(tmpdir(), 'maka launcher release '));
  try {
    const version = '0.2.0-rust-preview.1';
    const root = 'apache-maka-0.2.0-incubating';
    const sourceRoot = join(stage, root);
    await mkdir(join(sourceRoot, 'packages/cli/bin'), { recursive: true });
    for (const file of ['package.json', 'README.md', 'README.zh-CN.md', 'bin/maka.mjs']) {
      await copyFile(
        join(import.meta.dirname, '../../packages/cli', file),
        join(sourceRoot, 'packages/cli', file),
      );
    }
    for (const [file, content] of Object.entries({
      'package.json': JSON.stringify({ name: 'maka', version: '0.2.0', license: 'Apache-2.0' }),
      'package-lock.json': JSON.stringify({
        version: '0.2.0',
        lockfileVersion: 3,
        packages: { '': { version: '0.2.0' } },
      }),
      LICENSE: 'Apache License, Version 2.0\n',
      NOTICE: 'Apache Maka\n',
      'DISCLAIMER-WIP': 'Apache Maka is undergoing incubation.\n',
    }))
      await writeFile(join(sourceRoot, file), content);
    const archive = root + '-src.tar.gz';
    execFileSync('tar', ['-czf', join(stage, archive), '-C', stage, root]);
    const sha512 = createHash('sha512')
      .update(await readFile(join(stage, archive)))
      .digest('hex');
    await writeFile(join(stage, archive + '.sha512'), `${sha512}  ${archive}\n`);
    const source = { archive, version: '0.2.0', sha512 };
    await mkdir(join(stage, 'package'));
    for (const target of previewTargets) {
      const name = '@maka-agent/cli-' + target;
      const archive = 'maka-agent-cli-' + target + '-' + version + '.tgz';
      await writeFile(
        join(stage, 'package/package.json'),
        JSON.stringify({
          name,
          version,
          makaSource: source,
          publishConfig: { tag: 'rust-preview' },
        }),
      );
      execFileSync('tar', ['-czf', join(stage, archive), '-C', stage, 'package']);
      const integrity =
        'sha512-' +
        createHash('sha512')
          .update(await readFile(join(stage, archive)))
          .digest('base64');
      await writeFile(
        join(stage, target + '.json'),
        JSON.stringify({ name, version, target, archive, integrity }),
      );
    }
    await assert.rejects(readPreviewRelease(stage), /ENOENT/);
    const receipt = await packLauncher(stage);
    const packages = await readPreviewRelease(stage);
    assert.deepEqual(
      packages.map(({ name }) => name),
      [...previewTargets.map((target) => '@maka-agent/cli-' + target), '@maka-agent/cli'],
    );
    const packed = join(stage, receipt.archive);
    const files = execFileSync('tar', ['-tzf', packed], { encoding: 'utf8' })
      .trim()
      .split('\n')
      .sort();
    assert.deepEqual(
      files,
      [
        'package/LICENSE',
        'package/NOTICE',
        'package/README.md',
        'package/README.zh-CN.md',
        'package/bin/maka.mjs',
        'package/package.json',
      ].sort(),
    );
    assert.equal(
      execFileSync('tar', ['-xOf', packed, 'package/bin/maka.mjs'], { encoding: 'utf8' }),
      await readFile(join(sourceRoot, 'packages/cli/bin/maka.mjs'), 'utf8'),
    );
    const manifest = JSON.parse(
      execFileSync('tar', ['-xOf', packed, 'package/package.json'], { encoding: 'utf8' }),
    );
    assert.deepEqual(
      manifest.optionalDependencies,
      Object.fromEntries(previewTargets.map((target) => ['@maka-agent/cli-' + target, version])),
    );
    assert.match(manifest.description, /Unofficial experimental.*not an ASF release/);
    const readme = execFileSync('tar', ['-xOf', packed, 'package/README.md'], { encoding: 'utf8' });
    assert.match(
      readme,
      /not an official Apache Software Foundation release and is not approved, endorsed or supported by the ASF/,
    );
    assert.match(
      readme,
      /The `latest` tags remain empty placeholders, including the separate `maka-agent` package\. They contain no CLI, runtime, dependencies or install scripts\./,
    );
    assert.deepEqual(manifest.makaSource, source);
    await publicationRecovery(t, stage, packages);
    await writeFile(packed, 'tampered');
    await assert.rejects(readPreviewRelease(stage), /integrity differs/);
    await writeFile(join(stage, archive), 'tampered source');
    await assert.rejects(packLauncher(stage), /SHA-512 mismatch/);
  } finally {
    await rm(stage, { recursive: true, force: true });
  }
});

async function publicationRecovery(t, directory, packages) {
  const versions = new Map();
  const tags = new Map();
  const uploads = [];
  const originalExec = childProcess.execFileSync;
  let fail = true;
  let raced = false;
  let tagReads = 0;
  let pendingVisibility = 6;
  // Advance confirmation waits without making this registry simulation sleep.
  const delay = t.mock.method(globalThis, 'setTimeout', (resolveDelay) => {
    queueMicrotask(resolveDelay);
    return 0;
  });
  const fetch = t.mock.method(globalThis, 'fetch', async (url) => {
    const path = new URL(url).pathname;
    if (path.startsWith('/-/package/')) {
      const name = decodeURIComponent(path.slice('/-/package/'.length, -'/dist-tags'.length));
      if (raced && ++tagReads > packages.length) tags.set(name, '0.2.0-rust-preview.999');
      return new Response(JSON.stringify(tags.has(name) ? { 'rust-preview': tags.get(name) } : {}));
    }
    const pkg = packages.find((pkg) => path === '/' + pkg.name + '/' + pkg.version);
    assert.ok(pkg, 'only fixture registry paths may be read');
    if (versions.has(pkg.name) && pkg.name === packages[0].name && pendingVisibility > 0) {
      pendingVisibility -= 1;
      return new Response('', { status: 404 });
    }
    return versions.has(pkg.name)
      ? new Response(JSON.stringify({ dist: { integrity: versions.get(pkg.name) } }))
      : new Response('', { status: 404 });
  });
  const exec = t.mock.method(childProcess, 'execFileSync', (command, args, options) => {
    if (command === 'tar') return originalExec(command, args, options);
    assert.equal(command, 'npm');
    if (args[0] === 'publish') {
      const pkg = packages.find((pkg) => pkg.archive === join(options.cwd, args[1]));
      assert.ok(pkg, 'publish uses a cwd and basename even when the directory has spaces');
      assert.ok(!versions.has(pkg.name), 'accepted immutable versions are never uploaded again');
      versions.set(pkg.name, pkg.integrity);
      uploads.push(pkg.name);
      if (fail && uploads.length === 2) {
        fail = false;
        throw new Error('lost publication response');
      }
      tags.set(pkg.name, pkg.version);
    } else {
      assert.deepEqual(args.slice(0, 2), ['dist-tag', 'add']);
      const pkg = packages.find((pkg) => pkg.name + '@' + pkg.version === args[2]);
      assert.ok(pkg);
      assert.equal(versions.get(pkg.name), pkg.integrity);
      tags.set(pkg.name, pkg.version);
    }
    return '';
  });
  syncBuiltinESMExports();
  try {
    await assert.rejects(publishPreviewRelease(directory), /lost publication response/);
    await publishPreviewRelease(directory);
    assert.deepEqual(
      uploads,
      packages.map((pkg) => pkg.name),
    );
    assert.deepEqual([...tags].sort(), packages.map((pkg) => [pkg.name, pkg.version]).sort());
    tags.delete('@maka-agent/cli');
    await publishPreviewRelease(directory);
    assert.equal(tags.get('@maka-agent/cli'), packages[0].version);
    tags.set('@maka-agent/cli', '0.2.0-rust-preview.999');
    await assert.rejects(publishPreviewRelease(directory), /backwards/);
    assert.equal(tags.get('@maka-agent/cli'), '0.2.0-rust-preview.999');
    assert.equal(uploads.length, packages.length);
    versions.clear();
    tags.clear();
    raced = true;
    await assert.rejects(publishPreviewRelease(directory), /backwards/);
    assert.equal(
      uploads.length,
      packages.length,
      'a tag advanced after preflight prevents the first publication',
    );
  } finally {
    fetch.mock.restore();
    exec.mock.restore();
    delay.mock.restore();
    syncBuiltinESMExports();
  }
}

test('publication rejects incomplete, mixed-source, or modified platform sets before writing npm', async () => {
  const stage = await mkdtemp(join(tmpdir(), 'maka-publication-'));
  try {
    const version = '0.2.0-rust-preview.1';
    const source = {
      archive: 'apache-maka-0.2.0-incubating-src.tar.gz',
      version: '0.2.0',
      sha512: 'a'.repeat(128),
    };
    await mkdir(join(stage, 'package'));
    async function pack(target, origin = source) {
      const name = '@maka-agent/cli-' + target;
      const archive = 'maka-agent-cli-' + target + '-' + version + '.tgz';
      await writeFile(
        join(stage, 'package/package.json'),
        JSON.stringify({
          name,
          version,
          makaSource: origin,
          publishConfig: { tag: 'rust-preview' },
        }),
      );
      execFileSync('tar', ['-czf', join(stage, archive), '-C', stage, 'package']);
      const integrity =
        'sha512-' +
        createHash('sha512')
          .update(await readFile(join(stage, archive)))
          .digest('base64');
      await writeFile(
        join(stage, target + '.json'),
        JSON.stringify({ name, version, target, archive, integrity }),
      );
    }
    await pack(previewTargets[0]);
    await assert.rejects(readNativePreviewRelease(stage), /ENOENT/);
    for (const target of previewTargets.slice(1)) await pack(target);
    assert.equal((await readNativePreviewRelease(stage)).length, 3);
    await pack(previewTargets[2], { ...source, sha512: 'b'.repeat(128) });
    await assert.rejects(readNativePreviewRelease(stage), /same source archive/);
    await pack(previewTargets[2]);
    await writeFile(
      join(stage, 'maka-agent-cli-' + previewTargets[0] + '-' + version + '.tgz'),
      'changed',
    );
    await assert.rejects(readNativePreviewRelease(stage), /integrity differs/);
  } finally {
    await rm(stage, { recursive: true, force: true });
  }
});

test('preview builds have distinct package versions without changing the source version', () => {
  assert.equal(previewVersion('0.2.0', '20260916.1'), '0.2.0-rust-preview.20260916.1');
  assert.equal(previewVersion('0.2.0', '20260916.2'), '0.2.0-rust-preview.20260916.2');
  assert.equal(previewVersion('0.2.0', '123.2.gabc123'), '0.2.0-rust-preview.123.2.gabc123');
  for (const buildId of [undefined, '', '01', '1..2', '1+sha', 'a/b', 'a'.repeat(256)]) {
    assert.throws(
      () => previewVersion('0.2.0', buildId),
      /build-id|release version|256 characters/,
    );
  }
  assert.throws(() => previewVersion('0.2.0-beta', '1'), /stable source version/);
});

test('source identity failures cannot reach dependency installation or compilation', async () => {
  const stage = await mkdtemp(join(tmpdir(), 'maka-source-release-test-'));
  try {
    const name = 'apache-maka-1.2.3-incubating';
    const sourceRoot = join(stage, name);
    await mkdir(join(sourceRoot, 'src'), { recursive: true });
    const files = {
      LICENSE: 'Apache-2.0\n',
      NOTICE: 'Apache Maka\n',
      'DISCLAIMER-WIP': 'Apache Maka is undergoing incubation.\n',
      'package.json': JSON.stringify({ name: 'maka', version: '1.2.3', license: 'Apache-2.0' }),
      'package-lock.json': JSON.stringify({
        version: '1.2.3',
        lockfileVersion: 3,
        packages: { '': { version: '1.2.3' } },
      }),
      'Cargo.toml': '[package]\nname = "maka-cli"\nversion = "0.0.0"\nedition = "2024"\n',
      'src/main.rs': 'fn main() {}\n',
    };
    for (const [path, content] of Object.entries(files)) {
      await writeFile(join(sourceRoot, path), content);
    }
    const source = join(stage, name + '-src.tar.gz');
    execFileSync('tar', ['-czf', source, '-C', stage, name]);
    const digest = createHash('sha512')
      .update(await readFile(source))
      .digest('hex');
    await writeFile(source + '.sha512', digest + '  ' + name + '-src.tar.gz\n');
    const args = {
      buildId: '1',
      source,
      target: 'linux-x64-gnu',
      // Deliberately absent: source identity must fail before any of these is used.
      notices: join(stage, 'notices'),
      validator: join(stage, 'validator'),
      output: join(stage, 'output'),
    };
    await assert.rejects(releaseNativeCli(args), /Native CLI version does not match/);
    await writeFile(source, 'changed since the checksum was created');
    await assert.rejects(releaseNativeCli(args), /SHA-512 mismatch/);
    await assert.rejects(releaseNativeCli({ ...args, target: 'toString' }), /supported target/);
  } finally {
    await rm(stage, { recursive: true, force: true });
  }
});
