import {
  existsSync,
  mkdirSync,
  readFileSync,
  readdirSync,
  rmSync,
} from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { fileURLToPath } from "node:url";

const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const buildEnv = process.env.ELECTROBUN_BUILD_ENV || "dev";
const targetOs = process.env.ELECTROBUN_OS || "macos";
const wrapperPath = process.env.ELECTROBUN_WRAPPER_BUNDLE_PATH;

if (buildEnv === "dev" || targetOs !== "macos") {
  console.log("expand-macos-bundle: skipping (dev or non-macOS build)");
  process.exit(0);
}

if (!wrapperPath || !existsSync(wrapperPath)) {
  console.error("expand-macos-bundle: ELECTROBUN_WRAPPER_BUNDLE_PATH not set or missing");
  process.exit(1);
}

const resolvedWrapperPath = path.resolve(wrapperPath);
const contentsPath = path.join(resolvedWrapperPath, "Contents");
const resourcesPath = path.join(contentsPath, "Resources");
const metadataPath = path.join(resourcesPath, "metadata.json");

if (!existsSync(metadataPath)) {
  console.log("expand-macos-bundle: no extractor metadata, assuming already expanded");
  process.exit(0);
}

const metadata = JSON.parse(readFileSync(metadataPath, "utf8"));
const hash = metadata.hash;
const appName = metadata.name || "Farm Control";
const tarZstPath = path.resolve(resourcesPath, `${hash}.tar.zst`);

if (!existsSync(tarZstPath)) {
  console.log(`expand-macos-bundle: ${hash}.tar.zst not found, skipping`);
  process.exit(0);
}

function decompressTarZst(inputPath, outputPath) {
  const systemZstd = spawnSync("zstd", ["--version"], { encoding: "utf8" });
  if (systemZstd.status === 0) {
    return spawnSync("zstd", ["-d", "-f", "-o", outputPath, inputPath], {
      stdio: "inherit",
    });
  }

  const hostArch = process.arch === "arm64" ? "arm64" : "x64";
  const zigZstd = path.join(
    rootDir,
    "node_modules/electrobun/dist-macos-" + hostArch,
    "zig-zstd",
  );
  if (existsSync(zigZstd)) {
    return spawnSync(
      zigZstd,
      ["decompress", "-i", inputPath, "-o", outputPath, "--no-timing"],
      { stdio: "inherit" },
    );
  }

  console.error(
    "expand-macos-bundle: zstd not found (install zstd or use electrobun dist binaries)",
  );
  process.exit(1);
}

const workDir = path.join(tmpdir(), `farmcontrol-expand-${hash}`);
const tarPath = path.join(workDir, `${hash}.tar`);
rmSync(workDir, { recursive: true, force: true });
mkdirSync(workDir, { recursive: true });

const decompress = decompressTarZst(tarZstPath, tarPath);

if (decompress.status !== 0) {
  console.error("expand-macos-bundle: zstd decompression failed");
  process.exit(decompress.status ?? 1);
}

const extractTar = spawnSync("tar", ["-xf", tarPath, "-C", workDir], {
  stdio: "inherit",
});

if (extractTar.status !== 0) {
  console.error("expand-macos-bundle: tar extraction failed");
  process.exit(extractTar.status ?? 1);
}

const innerAppPath = path.join(workDir, `${appName}.app`);
if (!existsSync(innerAppPath)) {
  const appBundle = readdirSync(workDir).find((entry) => entry.endsWith(".app"));
  if (!appBundle) {
    console.error("expand-macos-bundle: extracted app bundle not found");
    process.exit(1);
  }
}

const resolvedInnerApp = existsSync(innerAppPath)
  ? innerAppPath
  : path.join(workDir, readdirSync(workDir).find((e) => e.endsWith(".app")));
const innerContentsPath = path.join(resolvedInnerApp, "Contents");

function replaceDirectory(sourceDir, destinationDir) {
  rmSync(destinationDir, { recursive: true, force: true });
  const result = spawnSync("ditto", [sourceDir, destinationDir], {
    stdio: "inherit",
  });
  if (result.status !== 0) {
    console.error("expand-macos-bundle: ditto copy failed");
    process.exit(result.status ?? 1);
  }
}

replaceDirectory(
  path.join(innerContentsPath, "MacOS"),
  path.join(contentsPath, "MacOS"),
);

rmSync(resourcesPath, { recursive: true, force: true });
replaceDirectory(path.join(innerContentsPath, "Resources"), resourcesPath);

const innerFrameworks = path.join(innerContentsPath, "Frameworks");
const wrapperFrameworks = path.join(contentsPath, "Frameworks");
if (existsSync(innerFrameworks)) {
  replaceDirectory(innerFrameworks, wrapperFrameworks);
}

const infoPlistResult = spawnSync(
  "ditto",
  [path.join(innerContentsPath, "Info.plist"), path.join(contentsPath, "Info.plist")],
  { stdio: "inherit" },
);
if (infoPlistResult.status !== 0) {
  console.error("expand-macos-bundle: Info.plist copy failed");
  process.exit(infoPlistResult.status ?? 1);
}

rmSync(workDir, { recursive: true, force: true });

if (process.platform === "darwin") {
  spawnSync("xattr", ["-cr", resolvedWrapperPath], { stdio: "inherit" });
}

console.log(`expand-macos-bundle: pre-expanded ${resolvedWrapperPath}`);
