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

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

const requiredFiles = [
  "src/bun/index.js",
  "electrobun.config.ts",
  "package.json",
];

for (const relativePath of requiredFiles) {
  const filePath = path.join(rootDir, relativePath);
  if (!existsSync(filePath)) {
    console.error(`pre-build: required file not found: ${relativePath}`);
    process.exit(1);
  }
}

if (buildEnv === "stable" && process.env.ELECTROBUN_OS === "macos") {
  const codesignVars = [
    "ELECTROBUN_DEVELOPER_ID",
    "ELECTROBUN_APPLEID",
    "ELECTROBUN_APPLEIDPASS",
    "ELECTROBUN_TEAMID",
  ];
  const missing = codesignVars.filter((name) => !process.env[name]);

  if (missing.length > 0) {
    console.warn(
      `pre-build: stable macOS build without code signing credentials (${missing.join(", ")}); Electrobun will skip signing.`,
    );
  }
}

const buildMacosEffects = spawnSync(
  "bun",
  [path.join(rootDir, "scripts/build-macos-effects.mjs")],
  { cwd: rootDir, stdio: "inherit", env: process.env },
);

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

if (process.platform === "darwin") {
  const { validateMacosEffectsDylib, outFile } = await import(
    pathToFileURL(
      path.join(rootDir, "scripts/build-macos-effects.mjs"),
    ).href
  );

  if (!validateMacosEffectsDylib({ dylibPath: outFile })) {
    console.error(
      "pre-build: macOS window effects dylib is missing or invalid; blur and traffic lights will not work in packaged builds.",
    );
    process.exit(1);
  }
}

const requiredIconPaths = [
  path.join(rootDir, "assets/icon.ico"),
  path.join(rootDir, "assets/icon.png"),
  path.join(rootDir, "assets/icon.iconset/icon_256x256.png"),
  path.join(rootDir, "assets/installer.ico"),
  path.join(rootDir, "assets/uninstaller.ico"),
];

if (buildEnv === "stable") {
  const prepareIcons = spawnSync(
    "bun",
    [path.join(rootDir, "scripts/generate-app-icons.mjs")],
    { cwd: rootDir, stdio: "inherit", env: process.env },
  );

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

const missingIcons = requiredIconPaths.filter((filePath) => !existsSync(filePath));
if (missingIcons.length > 0) {
  console.error(
    `pre-build: missing generated icons:\n${missingIcons
      .map((filePath) => `  - ${path.relative(rootDir, filePath)}`)
      .join("\n")}\nRun \`bun run generate-app-icons\` to create them.`,
  );
  process.exit(1);
}

const writeBuildInfo = spawnSync(
  "bun",
  [path.join(rootDir, "scripts/write-build-info.mjs")],
  { cwd: rootDir, stdio: "inherit", env: process.env },
);

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

if (buildEnv === "dev") {
  console.log(
    "pre-build: dev environment — skipping production renderer build (use dev:renderer for Vite)",
  );

  // Electrobun still copies dist/mainview into the app bundle; provide a stub so
  // dev builds don't warn when Vite serves the renderer instead.
  const stubDir = path.join(rootDir, "dist/mainview");
  mkdirSync(stubDir, { recursive: true });
  writeFileSync(
    path.join(stubDir, "index.html"),
    "<!doctype html><html><body>Dev mode — start Vite with <code>bun run dev:renderer</code>.</body></html>",
  );

  console.log(`pre-build: validation passed (${buildEnv})`);
  process.exit(0);
}

const buildRenderer = spawnSync(
  "bun",
  [path.join(rootDir, "scripts/build-renderer.mjs")],
  {
    cwd: rootDir,
    stdio: "inherit",
    env: {
      ...process.env,
      NODE_ENV: "production",
    },
  },
);

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

const rendererIndex = path.join(rootDir, "dist/mainview/index.html");
if (!existsSync(rendererIndex)) {
  console.error(`pre-build: renderer output not found: dist/mainview/index.html`);
  process.exit(1);
}

console.log(`pre-build: validation and renderer build passed (${buildEnv})`);
