'use strict';

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const browserInstall = require('./browser-install');
const { target } = require('./platform');
const { expectedArchives, verifyArtifactFiles } = require('./release-contract-test');

const root = path.join(__dirname, '..');
const nativeDir = path.join(root, 'native');

assert.deepEqual(target('linux', 'x64'), {
  os: 'linux',
  arch: 'amd64',
  ext: '',
  archiveExt: '.tar.gz',
});
assert.deepEqual(target('darwin', 'arm64'), {
  os: 'darwin',
  arch: 'arm64',
  ext: '',
  archiveExt: '.tar.gz',
});
assert.deepEqual(target('win32', 'x64'), {
  os: 'windows',
  arch: 'amd64',
  ext: '.exe',
  archiveExt: '.zip',
});
assert.throws(() => target('win32', 'arm64'), /windows\/arm64/);
assert.throws(() => target('freebsd', 'x64'), /Unsupported platform/);
assert.throws(() => target('linux', 'ia32'), /Unsupported architecture/);

assert.equal(browserInstall.platformKey('darwin', 'arm64'), 'darwin-arm64');
assert.equal(browserInstall.platformKey('linux', 'x64'), 'linux-x64');
assert.equal(browserInstall.platformKey('win32', 'x64'), 'win32-x64');

assert.deepEqual(expectedArchives('1.0.0'), [
  'aget_1.0.0_linux_amd64.tar.gz',
  'aget_1.0.0_linux_arm64.tar.gz',
  'aget_1.0.0_darwin_amd64.tar.gz',
  'aget_1.0.0_darwin_arm64.tar.gz',
  'aget_1.0.0_windows_amd64.zip',
]);
verifyArtifactFiles([
  'aget_1.0.0_linux_amd64.tar.gz',
  'aget_1.0.0_linux_arm64.tar.gz',
  'aget_1.0.0_darwin_amd64.tar.gz',
  'aget_1.0.0_darwin_arm64.tar.gz',
  'aget_1.0.0_windows_amd64.zip',
  'checksums.txt',
], '1.0.0');
assert.throws(() => verifyArtifactFiles([
  'aget_0.0.0_linux_amd64.tar.gz',
  'checksums.txt',
], '1.0.0'), /missing snapshot archive/);

const info = target();
const binaryPath = path.join(nativeDir, `aget${info.ext}`);
const fake = process.platform === 'win32'
  ? '#!/usr/bin/env node\r\nconsole.log(`aget smoke ${process.argv.slice(2).join(" ")}`);\r\n'
  : '#!/bin/sh\necho "aget smoke $*"\n';

const nativeExisted = fs.existsSync(nativeDir);
const binaryExisted = fs.existsSync(binaryPath);
const originalBinary = binaryExisted ? fs.readFileSync(binaryPath) : null;
const originalMode = binaryExisted ? fs.statSync(binaryPath).mode & 0o777 : null;

try {
  fs.mkdirSync(nativeDir, { recursive: true });
  fs.writeFileSync(binaryPath, fake, { mode: 0o755 });
  fs.chmodSync(binaryPath, 0o755);

  const result = spawnSync(process.execPath, [path.join(root, 'bin', 'aget.js'), 'arg-one'], {
    cwd: root,
    encoding: 'utf8',
  });

  assert.equal(result.status, 0, result.stderr || result.stdout);
  assert.match(result.stdout, /aget smoke/);

  console.log('smoke ok');
} finally {
  if (binaryExisted) {
    fs.writeFileSync(binaryPath, originalBinary, { mode: originalMode });
    fs.chmodSync(binaryPath, originalMode);
  } else {
    fs.rmSync(binaryPath, { force: true });
  }

  if (!nativeExisted && fs.existsSync(nativeDir) && fs.readdirSync(nativeDir).length === 0) {
    fs.rmdirSync(nativeDir);
  }
}
