const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');

const rootDir = path.resolve(__dirname, '..');
const serverPackageJsonPath = path.join(rootDir, 'server', 'package.json');
const serverEntryPointPath = path.join(rootDir, 'server', 'dist', 'index.js');
const serverSqlJsBinaryPath = path.join(rootDir, 'server', 'node_modules', 'sql.js', 'dist', 'sql-wasm.wasm');
const distServerDir = path.join(rootDir, 'dist-server');

function parseArgs(argv) {
  const args = {};

  for (let index = 0; index < argv.length; index += 1) {
    const token = argv[index];

    if (!token.startsWith('--')) {
      continue;
    }

    const key = token.slice(2);
    const nextToken = argv[index + 1];

    if (!nextToken || nextToken.startsWith('--')) {
      args[key] = true;
      continue;
    }

    args[key] = nextToken;
    index += 1;
  }

  return args;
}

function resolvePkgBinPath() {
  const pkgPackageJsonPath = require.resolve('pkg/package.json');

  return path.join(path.dirname(pkgPackageJsonPath), 'lib-es5', 'bin.js');
}

function copySqlJsBinary() {
  if (!fs.existsSync(serverSqlJsBinaryPath)) {
    throw new Error(`sql.js wasm binary not found at ${serverSqlJsBinaryPath}. Run npm install --prefix server first.`);
  }

  fs.copyFileSync(
    serverSqlJsBinaryPath,
    path.join(distServerDir, 'sql-wasm.wasm')
  );
}

function main() {
  const args = parseArgs(process.argv.slice(2));
  const target = typeof args.target === 'string' && args.target.trim().length > 0
    ? args.target.trim()
    : null;
  const outputName = typeof args.output === 'string' && args.output.trim().length > 0
    ? args.output.trim()
    : null;

  if (!target) {
    throw new Error('A pkg target is required. Pass it with --target.');
  }

  if (!outputName) {
    throw new Error('An output file name is required. Pass it with --output.');
  }

  if (!fs.existsSync(serverEntryPointPath)) {
    throw new Error(`Server build output not found at ${serverEntryPointPath}. Run npm run server:build first.`);
  }

  fs.mkdirSync(distServerDir, { recursive: true });

  const outputPath = path.join(distServerDir, outputName);

  if (fs.existsSync(outputPath)) {
    fs.rmSync(outputPath, { force: true });
  }

  const pkgBinPath = resolvePkgBinPath();
  const result = spawnSync(process.execPath, [
    pkgBinPath,
    serverPackageJsonPath,
    '--targets',
    target,
    '--output',
    outputPath
  ], {
    cwd: rootDir,
    stdio: 'inherit'
  });

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

  copySqlJsBinary();

  console.log(`[server-bundle] Wrote ${outputPath}`);
}

try {
  main();
} catch (error) {
  const message = error instanceof Error ? error.message : String(error);

  console.error(`[server-bundle] ${message}`);
  process.exitCode = 1;
}
