/**
 * Copy necessary dependencies after packaging
 * Based on https://ganeshrvel.medium.com/electron-builder-afterpack-configuration-5c2c986be665
 * Adapted for electron forge https://github.com/electron-userland/electron-forge/issues/2248
 */
import fs from 'fs-extra';
import path from 'path';

/**
 * Running afterPack hook
 * Note: This must be a non-async function that accepts a callback for Electron Packager compatibility
 * @param buildPath /var/folders/qj/7j0zx32d0l75zmnrl1w3m3b80000gn/T/electron-packager/darwin-x64/TidGi-darwin-x64/Electron.app/Contents/Resources/app
 * @param electronVersion 12.0.6
 * @param platform darwin / win32 (even on win11 x64)
 * @param arch x64
 * @param callback Callback to signal completion
 */
export default (
  buildPath: string,
  _electronVersion: string,
  _platform: string,
  _arch: string,
  callback: () => void,
): void => {
  const cwd = path.resolve(buildPath, '..');
  const projectRoot = path.resolve(__dirname, '..');

  console.log('Copy npm packages with node-worker dependencies with binary (dugite) or __filename usages (tiddlywiki), which cannot be prepared properly by webpack');

  if (['production', 'test'].includes(process.env.NODE_ENV ?? '')) {
    console.log('Copying tiddlywiki dependency to dist');
    const sourceNodeModulesFolder = path.resolve(projectRoot, 'node_modules');

    fs.cpSync(
      path.join(sourceNodeModulesFolder, 'zx'),
      path.join(cwd, 'node_modules', 'zx'),
      { dereference: true, recursive: true },
    );

    const packagePathsToCopyDereferenced: string[][] = [
      ['tiddlywiki', 'package.json'],
      ['tiddlywiki', 'boot'],
      ['tiddlywiki', 'core'],
      // only copy plugins that is used in src/services/wiki/wikiWorker/startNodeJSWiki.ts, other plugins can be installed via JSON from online plugin library
      ['tiddlywiki', 'plugins', 'linonetwo'],
      ['tiddlywiki', 'plugins', 'tiddlywiki', 'filesystem'],
      ['tiddlywiki', 'plugins', 'tiddlywiki', 'tiddlyweb'],
      ['tiddlywiki', 'tiddlywiki.js'],
      // we only need its `main` binary, no need its dependency and code, because we already copy it to src/services/native/externalApp
      ['app-path', 'main'],
      // node binary
      ['better-sqlite3', 'build', 'Release', 'better_sqlite3.node'],
      // nsfw native module
      ['nsfw', 'build', 'Release', 'nsfw.node'],
      // Refer to `node_modules\sqlite-vec\index.cjs` for latest file names
      // sqlite-vec: copy main entry files and platform-specific binary
      ['sqlite-vec', 'package.json'],
      ['sqlite-vec', 'index.cjs'],
      [`sqlite-vec-${process.platform === 'win32' ? 'windows' : process.platform}-${process.arch}`],
    ];

    console.log('Copying packagePathsToCopyDereferenced');
    for (const packagePathInNodeModules of packagePathsToCopyDereferenced) {
      // some binary may not exist in other platforms, so allow failing here.
      try {
        fs.copySync(
          path.resolve(sourceNodeModulesFolder, ...packagePathInNodeModules),
          path.resolve(cwd, 'node_modules', ...packagePathInNodeModules),
          { dereference: true },
        );
      } catch (error) {
        // some binary may not exist in other platforms, so allow failing here.
        const errorMessage = error instanceof Error ? error.message : String(error);
        console.error(
          `Error copying ${packagePathInNodeModules.join('/')} to dist, in afterPack.ts: ${errorMessage}`,
        );
      }
    }

    console.log('Copy dugite');
    // it has things like `git/bin/libexec/git-core/git-add` link to `git/bin/libexec/git-core/git`, to reduce size, so can't use `dereference: true, recursive: true` here.
    fs.copySync(
      path.join(sourceNodeModulesFolder, 'dugite'),
      path.join(cwd, 'node_modules', 'dugite'),
      { dereference: false },
    );
  }

  /** complete this hook */
  callback();
};
