#!/usr/bin/env node

import * as FS from "node:fs";
import * as Path from "node:path";

class BuildNixDesktopPackageError extends Error {
  constructor(message) {
    super(message);
    this.name = "BuildNixDesktopPackageError";
  }
}

function parseArgs(argv) {
  let outputDir;

  for (let index = 0; index < argv.length; index += 1) {
    const arg = argv[index];
    if (arg === "--output-dir") {
      outputDir = argv[index + 1];
      index += 1;
    }
  }

  if (!outputDir) {
    throw new BuildNixDesktopPackageError("Missing required --output-dir argument.");
  }

  return { outputDir };
}

function assertPathExists(path, description) {
  if (!FS.existsSync(path)) {
    throw new BuildNixDesktopPackageError(
      `Missing ${description} at ${path}. Run 'bun run build:desktop' first.`,
    );
  }
}

function readJson(path) {
  return JSON.parse(FS.readFileSync(path, "utf8"));
}

function main() {
  const { outputDir } = parseArgs(process.argv.slice(2));
  const repoRoot = process.cwd();
  const packagedAppDir = Path.resolve(repoRoot, outputDir);

  const rootPackageJson = readJson(Path.join(repoRoot, "package.json"));
  const desktopPackageJson = readJson(Path.join(repoRoot, "apps/desktop/package.json"));
  const serverPackageJson = readJson(Path.join(repoRoot, "apps/server/package.json"));

  const desktopDistDir = Path.join(repoRoot, "apps/desktop/dist-electron");
  const desktopResourcesDir = Path.join(repoRoot, "apps/desktop/resources");
  const serverDistDir = Path.join(repoRoot, "apps/server/dist");
  const bundledClientIndex = Path.join(serverDistDir, "client/index.html");

  assertPathExists(desktopDistDir, "desktop bundle");
  assertPathExists(Path.join(desktopDistDir, "main.cjs"), "desktop main entry");
  assertPathExists(Path.join(desktopDistDir, "preload.cjs"), "desktop preload entry");
  assertPathExists(desktopResourcesDir, "desktop resources");
  assertPathExists(serverDistDir, "server bundle");
  assertPathExists(Path.join(serverDistDir, "bin.mjs"), "server entry");
  assertPathExists(bundledClientIndex, "bundled desktop web client");

  FS.rmSync(packagedAppDir, { recursive: true, force: true });
  FS.mkdirSync(Path.join(packagedAppDir, "apps/desktop"), { recursive: true });
  FS.mkdirSync(Path.join(packagedAppDir, "apps/server"), { recursive: true });

  FS.cpSync(desktopDistDir, Path.join(packagedAppDir, "apps/desktop/dist-electron"), {
    recursive: true,
  });
  FS.cpSync(desktopResourcesDir, Path.join(packagedAppDir, "apps/desktop/resources"), {
    recursive: true,
  });
  FS.cpSync(serverDistDir, Path.join(packagedAppDir, "apps/server/dist"), {
    recursive: true,
  });

  const packageJson = {
    name: "t3code",
    version: serverPackageJson.version ?? desktopPackageJson.version,
    private: true,
    description: "T3 Code desktop build",
    author: "T3 Tools",
    main: "apps/desktop/dist-electron/main.cjs",
    t3codeCommitHash: "unknown",
    packageManager: rootPackageJson.packageManager,
  };

  FS.writeFileSync(
    Path.join(packagedAppDir, "package.json"),
    `${JSON.stringify(packageJson, null, 2)}\n`,
    "utf8",
  );
}

main();
