import assert from 'node:assert/strict';
import { execFileSync, spawnSync } from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';

const root = path.resolve(import.meta.dirname, '..');
const builder = path.join(root, 'tools/build-map-source-pk4.py');
const source = path.join(root, 'mods/maps/q4web_arena');

test('self-authored map source PK4 is canonical and reproducible', (t) => {
  const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'q4-map-pk4-'));
  t.after(() => fs.rmSync(temporary, { recursive: true, force: true }));
  const first = path.join(temporary, 'first.pk4');
  const second = path.join(temporary, 'second.pk4');

  const firstResult = JSON.parse(execFileSync('python3', [
    builder, '--source', source, '--output', first,
  ], { encoding: 'utf8' }));
  const secondResult = JSON.parse(execFileSync('python3', [
    builder, '--source', source, '--output', second,
  ], { encoding: 'utf8' }));

  assert.equal(firstResult.sha256, secondResult.sha256);
  assert.deepEqual(fs.readFileSync(first), fs.readFileSync(second));
  assert.deepEqual(firstResult.entries, [
    'maps/mp/q4web_arena.aas32',
    'maps/mp/q4web_arena.cm',
    'maps/mp/q4web_arena.map',
    'maps/mp/q4web_arena.proc',
  ]);
  assert.deepEqual(
    execFileSync('unzip', ['-Z1', first], { encoding: 'utf8' }).trim().split('\n'),
    firstResult.entries,
  );
  const listing = execFileSync('zipinfo', ['-l', first], { encoding: 'utf8' });
  assert.equal((listing.match(/^-rw-r--r--/gm) || []).length, firstResult.entries.length);
});

test('deterministic map builder rejects symlinks', (t) => {
  const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'q4-map-pk4-link-'));
  t.after(() => fs.rmSync(temporary, { recursive: true, force: true }));
  const maps = path.join(temporary, 'maps/mp');
  fs.mkdirSync(maps, { recursive: true });
  for (const extension of ['map', 'proc', 'cm']) {
    fs.writeFileSync(path.join(maps, `test.${extension}`), `fixture ${extension}\n`);
  }
  fs.symlinkSync(path.join(maps, 'test.map'), path.join(maps, 'test.aas32'));

  const result = spawnSync('python3', [
    builder, '--source', temporary, '--output', path.join(temporary, 'test.pk4'),
  ], { encoding: 'utf8' });
  assert.notEqual(result.status, 0);
  assert.match(result.stderr, /contains a symlink/);
});
