#!/usr/bin/env node

import { promises as fs } from 'node:fs';
import path from 'node:path';
import { transform } from 'esbuild';

const TARGET = 'chrome83';
const UNSUPPORTED_LOGICAL_ASSIGNMENT = /(\?\?=|\|\|=|&&=)/;

async function pathExists(filePath) {
  try {
    await fs.access(filePath);
    return true;
  } catch {
    return false;
  }
}

async function collectJavaScriptFiles(rootDir) {
  const entries = await fs.readdir(rootDir, { withFileTypes: true });
  const files = [];

  for (const entry of entries) {
    const entryPath = path.join(rootDir, entry.name);

    if (entry.isDirectory()) {
      files.push(...await collectJavaScriptFiles(entryPath));
      continue;
    }

    if (entry.isFile() && entry.name.endsWith('.js')) {
      files.push(entryPath);
    }
  }

  return files;
}

async function transpileFile(filePath) {
  const source = await fs.readFile(filePath, 'utf8');
  const result = await transform(source, {
    target: TARGET,
    loader: 'js',
    minify: true,
    legalComments: 'none',
  });

  await fs.writeFile(filePath, result.code);

  if (UNSUPPORTED_LOGICAL_ASSIGNMENT.test(result.code)) {
    throw new Error(`${filePath} still contains logical assignment syntax after ${TARGET} transpilation.`);
  }
}

async function main() {
  const roots = process.argv.slice(2);
  const assetRoots = roots.length > 0 ? roots : ['.next/static', '.vercel/output/static/_next/static'];
  let processedFiles = 0;
  let existingRoots = 0;

  for (const root of assetRoots) {
    const rootDir = path.resolve(process.cwd(), root);

    if (!await pathExists(rootDir)) {
      continue;
    }

    existingRoots += 1;
    const files = await collectJavaScriptFiles(rootDir);

    for (const file of files) {
      await transpileFile(file);
      processedFiles += 1;
    }
  }

  if (existingRoots === 0) {
    console.log(`No client asset directories found for ${TARGET} transpilation.`);
    return;
  }

  console.log(`Transpiled ${processedFiles} client JavaScript asset(s) for ${TARGET}.`);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
