// Code copied from [Rome](https://github.com/rome/tools/blob/main/npm/rome/scripts/generate-packages.mjs)

import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import * as fs from "node:fs";

const OXC_ROOT = resolve(fileURLToPath(import.meta.url), "../..");
console.log(OXC_ROOT);
const PACKAGES_ROOT = resolve(OXC_ROOT, "..");
const BINARY_ROOT = resolve(OXC_ROOT, "../../crates/oxc_napi");
const MANIFEST_PATH = resolve(OXC_ROOT, "package.json");

const rootManifest = JSON.parse(
  fs.readFileSync(MANIFEST_PATH).toString("utf-8")
);

function generateNativePackage(target) {
  const packageName = `@oxidation-compiler/napi-${target}`;
  const binaryName = `napi.${target}.node`;

  const packageRoot = resolve(PACKAGES_ROOT, `napi-${target}`);
  const binarySource = resolve(BINARY_ROOT, binaryName);
  const binaryTarget = resolve(packageRoot, binaryName);

  // Remove the directory just in case it already exists (it's autogenerated
  // so there shouldn't be anything important there anyway)
  fs.rmSync(packageRoot, { recursive: true, force: true });

  // Create the package directory
  console.log(`Create directory ${packageRoot}`);
  fs.mkdirSync(packageRoot);

  // Generate the package.json manifest
  const { version, license, repository } = rootManifest;

  const [os, cpu, third] = target.split("-");
  const manifest = {
    name: packageName,
    version,
    main: binaryName,
    files: [binaryName],
    os: [os],
    cpu: [cpu],
    license,
    repository
  };

  if (cpu == "linux" && third == "gnu") {
    manifest.libc = ["glibc"];
  }

  const manifestPath = resolve(packageRoot, "package.json");
  console.log(`Create manifest ${manifestPath}`);
  fs.writeFileSync(manifestPath, JSON.stringify(manifest));

  console.log(`Copy binary ${binaryTarget}`);
  fs.copyFileSync(binarySource, binaryTarget);
}

function writeManifest(packagePath) {
  const packageRoot = resolve(PACKAGES_ROOT, packagePath);
  const manifestPath = resolve(packageRoot, "package.json");

  const manifestData = JSON.parse(
    fs.readFileSync(manifestPath).toString("utf-8")
  );

  const nativePackages = TARGETS.map((target) => [
    `@oxidation-compiler/napi-${target}`,
    rootManifest.version,
  ]);

  manifestData["version"] = rootManifest.version;
  manifestData["optionalDependencies"] = Object.fromEntries(nativePackages);

  console.log(`Update manifest ${manifestPath}`);
  const content = JSON.stringify(manifestData);
  fs.writeFileSync(manifestPath, content);

  let files = ["index.js", "index.d.ts"];
  for (const file of files) {
    fs.copyFileSync(resolve(BINARY_ROOT, file), resolve(packageRoot, file));
  }
}

const TARGETS = [
  "win32-x64-msvc",
  "win32-arm64-msvc",
  "linux-x64-gnu",
  "linux-arm64-gnu",
  "darwin-x64",
  "darwin-arm64",
];

for (const target of TARGETS) {
  generateNativePackage(target);
}

writeManifest("napi");
