// Post-pack hook for Linux builds.
//
// Renames the main Electron binary to `superproductivity-bin` and installs
// a shell wrapper at the original name. The wrapper forces
// --class=superproductivity for stable desktop-file matching and forces
// --ozone-platform=x11 when running in our Snap sandbox on a Wayland session.
// Non-Snap launches (AppImage, .deb, .rpm) and X11 sessions only receive the
// stable class flag.
//
// Context: field reports on issue #7270 (v18.2.4/v18.2.5) show that
// app.commandLine.appendSwitch('ozone-platform','x11') from inside the
// main process is not equivalent to passing the flag on argv — Chromium's
// Ozone init in the browser process dlopens libEGL/libgbm on the core22
// Mesa path before the switch is honored, which segfaults under Mesa ABI
// drift. Injecting the flag via argv before Electron starts bypasses this.
//
// See docs/research/snap-wayland-gpu-fix-research.md §18.

const { promises: fs } = require('fs');
const { join } = require('path');

const BIN_NAME = 'superproductivity'; // must match linux.executableName
const RENAMED = 'superproductivity-bin';
const WRAPPER_SRC = join(__dirname, '..', 'build', 'linux', 'snap-wrapper.sh');
const WAYLAND_IDLE_HELPER_SRC = join(
  __dirname,
  '..',
  'electron',
  'bin',
  'wayland-idle-helper',
);
const WAYLAND_IDLE_HELPER_DEST = 'wayland-idle-helper';

const isTruthyEnv = (value) => value === '1' || value?.toLowerCase() === 'true';

async function afterPack(context) {
  if (context.electronPlatformName !== 'linux') return;

  const { appOutDir } = context;
  const binPath = join(appOutDir, BIN_NAME);
  const renamedPath = join(appOutDir, RENAMED);
  const helperDestPath = join(appOutDir, WAYLAND_IDLE_HELPER_DEST);

  const installWaylandIdleHelper = async () => {
    if (isTruthyEnv(process.env.SP_SKIP_WAYLAND_IDLE_HELPER_BUILD)) {
      console.warn(
        '[afterPack] Skipping Wayland idle helper copy because SP_SKIP_WAYLAND_IDLE_HELPER_BUILD is set',
      );
      return;
    }

    const helperStat = await fs.stat(WAYLAND_IDLE_HELPER_SRC).catch(() => null);
    if (!helperStat) {
      throw new Error(
        `[afterPack] ${WAYLAND_IDLE_HELPER_SRC} not found. Linux packages must include the Wayland idle helper; install Rust/Cargo before packaging or set SP_SKIP_WAYLAND_IDLE_HELPER_BUILD=1 to intentionally omit ext-idle-notify support.`,
      );
    }

    await fs.copyFile(WAYLAND_IDLE_HELPER_SRC, helperDestPath);
    await fs.chmod(helperDestPath, 0o755);
  };

  // Read wrapper content BEFORE touching appOutDir. If the source file is
  // missing or unreadable we fail fast with the Electron binary still in
  // place — no broken intermediate state.
  const wrapperContent = await fs.readFile(WRAPPER_SRC, 'utf8');

  const [binStat, renamedStat] = await Promise.all([
    fs.stat(binPath).catch(() => null),
    fs.stat(renamedPath).catch(() => null),
  ]);

  if (!binStat && !renamedStat) {
    console.warn(`[afterPack] ${binPath} not found; skipping wrapper install`);
    return;
  }

  // Idempotency: "already installed" requires both files + a shell shebang at
  // binPath. A shebang-less binPath co-existing with renamedPath means a
  // prior run crashed mid-way; fall through to re-write the wrapper.
  if (binStat && renamedStat) {
    const head = await fs.readFile(binPath, 'utf8').catch(() => '');
    if (head.startsWith('#!')) {
      await installWaylandIdleHelper();
      console.log(`[afterPack] wrapper already installed`);
      return;
    }
    throw new Error(
      `[afterPack] unexpected state at ${appOutDir}: both ${BIN_NAME} and ` +
        `${RENAMED} exist but ${BIN_NAME} is not a shell script. Refusing ` +
        `to overwrite; investigate manually.`,
    );
  }

  // Fresh install path: binStat exists, renamedStat doesn't → rename first.
  // Partial-recovery path: only renamedStat exists → skip rename, just
  // re-write the wrapper on top of the missing slot.
  if (!renamedStat) {
    await fs.rename(binPath, renamedPath);
  }

  try {
    await fs.writeFile(binPath, wrapperContent, { mode: 0o755 });
  } catch (err) {
    // Best-effort rollback so the build doesn't ship a pkg with no launcher.
    if (!renamedStat) {
      await fs.rename(renamedPath, binPath).catch(() => {});
    }
    throw err;
  }

  await fs.chmod(renamedPath, 0o755);
  await installWaylandIdleHelper();

  console.log(
    `[afterPack] Installed argv wrapper: ${BIN_NAME} -> ${RENAMED} + shell wrapper`,
  );
}

module.exports = afterPack;
