import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";
import { getReleaseArch, isBundleCefEnabled } from "./release-artifact-utils.mjs";

const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const hostArch = getReleaseArch(process.arch);
const targetArchs = process.env.ELECTROBUN_TARGET_ARCH
  ? [getReleaseArch(process.env.ELECTROBUN_TARGET_ARCH)]
  : ["arm64", "x64"];
const bundleCef = isBundleCefEnabled();

function canRunUnderArch(archFlag) {
  const result = spawnSync("arch", [archFlag, "true"], {
    encoding: "utf8",
    stdio: ["ignore", "pipe", "pipe"],
  });
  return result.status === 0;
}

function run(command, args, options = {}) {
  const result = spawnSync(command, args, {
    cwd: rootDir,
    stdio: "inherit",
    env: process.env,
    ...options,
  });

  if (result.status !== 0) {
    process.exit(result.status ?? 1);
  }
}

function buildElectrobunEnv(targetArch) {
  return {
    ...process.env,
    ELECTROBUN_BUILD_ENV: "stable",
    ELECTROBUN_OS: "macos",
    ELECTROBUN_ARCH: targetArch,
    ELECTROBUN_FORCE_ARCH: targetArch,
    ELECTROBUN_TARGET_ARCH: targetArch,
    NODE_ENV: "production",
  };
}

function getInvocation(targetArch) {
  const env = buildElectrobunEnv(targetArch);
  const runScript = path.join(rootDir, "scripts/run-electrobun-build.mjs");

  if (targetArch === hostArch) {
    return { command: "bun", args: [runScript], env };
  }

  if (targetArch === "x64" && hostArch === "arm64" && canRunUnderArch("-x86_64")) {
    return {
      command: "arch",
      args: ["-x86_64", "bun", runScript],
      env,
    };
  }

  if (targetArch === "arm64" && hostArch === "x64") {
    return { command: "bun", args: [runScript], env };
  }

  return null;
}

const orderedTargets = [...targetArchs].sort((a, b) => {
  if (a === hostArch) return -1;
  if (b === hostArch) return 1;
  return 0;
});

console.log(`Host architecture: ${hostArch}`);
console.log(`CEF bundling: ${bundleCef ? "enabled" : "disabled"}`);
console.log(`Build order: ${orderedTargets.join(", ")}`);

let builtCount = 0;

for (const targetArch of orderedTargets) {
  const invocation = getInvocation(targetArch);
  if (!invocation) {
    console.error(
      `Cannot build macOS ${targetArch} from host ${hostArch}.`,
    );
    continue;
  }

  console.log(`\n=== Building macOS ${targetArch} (host ${hostArch}, cef=${bundleCef}) ===`);
  console.log(
    `ELECTROBUN_BUILD_ENV=stable ELECTROBUN_OS=macos ELECTROBUN_ARCH=${targetArch} ELECTROBUN_BUNDLE_CEF=${bundleCef}\n`,
  );

  run(invocation.command, invocation.args, { env: invocation.env });
  builtCount += 1;
}

if (builtCount === 0) {
  console.error("No macOS architectures were built.");
  process.exit(1);
}

if (builtCount < targetArchs.length) {
  console.error(
    `Built ${builtCount}/${targetArchs.length} macOS architectures.`,
  );
  process.exit(1);
}

console.log(`\nBuilt macOS architectures: ${orderedTargets.join(", ")}`);
