import { existsSync, mkdirSync, statSync, writeFileSync } from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";

const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const srcFile = path.join(rootDir, "native/macos/window-effects.mm");
export const outFile = path.join(rootDir, "src/bun/libMacWindowEffects.dylib");
const minDylibBytes = 10_000;

function normalizeArch(value) {
  if (value === "x64" || value === "amd64" || value === "x86_64") {
    return "x86_64";
  }
  if (value === "arm64" || value === "aarch64") {
    return "arm64";
  }
  return null;
}

export function resolveTargetArch() {
  return (
    normalizeArch(process.env.ELECTROBUN_TARGET_ARCH) ||
    normalizeArch(process.env.ELECTROBUN_ARCH) ||
    normalizeArch(process.arch) ||
    "arm64"
  );
}

function createPlaceholder() {
  mkdirSync(path.dirname(outFile), { recursive: true });
  writeFileSync(outFile, "");
  console.log(`build-macos-effects: created placeholder dylib at ${outFile}`);
}

function readDylibArch(dylibPath) {
  const lipo = spawnSync("lipo", ["-info", dylibPath], { encoding: "utf8" });
  if (lipo.status === 0) {
    return lipo.stdout;
  }

  const file = spawnSync("file", ["-b", dylibPath], { encoding: "utf8" });
  return file.stdout || "";
}

export function validateMacosEffectsDylib({
  dylibPath = outFile,
  expectedArch = resolveTargetArch(),
  required = process.platform === "darwin",
} = {}) {
  if (!required) {
    return true;
  }

  if (!existsSync(dylibPath)) {
    console.error(`build-macos-effects: missing dylib at ${dylibPath}`);
    return false;
  }

  const { size } = statSync(dylibPath);
  if (size < minDylibBytes) {
    console.error(
      `build-macos-effects: dylib at ${dylibPath} is too small (${size} bytes)`,
    );
    return false;
  }

  const archInfo = readDylibArch(dylibPath);
  if (!archInfo.includes(expectedArch)) {
    console.error(
      `build-macos-effects: dylib architecture mismatch (expected ${expectedArch}): ${archInfo.trim()}`,
    );
    return false;
  }

  return true;
}

if (process.platform !== "darwin") {
  createPlaceholder();
  process.exit(0);
}

if (!existsSync(srcFile)) {
  console.error(`build-macos-effects: missing source file ${srcFile}`);
  process.exit(1);
}

mkdirSync(path.dirname(outFile), { recursive: true });

const targetArch = resolveTargetArch();
const result = spawnSync(
  "xcrun",
  [
    "clang++",
    "-dynamiclib",
    "-fobjc-arc",
    "-arch",
    targetArch,
    "-mmacosx-version-min=11.0",
    "-framework",
    "Cocoa",
    srcFile,
    "-o",
    outFile,
  ],
  { cwd: rootDir, stdio: "inherit" },
);

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

if (!validateMacosEffectsDylib({ dylibPath: outFile, expectedArch: targetArch })) {
  process.exit(1);
}

const { size } = statSync(outFile);
console.log(
  `build-macos-effects: built ${outFile} (${size} bytes, arch=${targetArch})`,
);
