/* eslint-disable @bigbinary/neeto/no-dangling-constants */
// Matches:
// const componentsContext = { App };
const COMPONENT_CONTEXT = /const\s+componentsContext\s*=\s*{[^}]+};?/;

// Matches:
// const App = React.lazy(() => import("src/App"));
const LAZY_LOAD_IMPORT =
  /const\s+(\w+)\s*=\s*React\.lazy\(\s*\(\)\s*=>\s*import\(["'](.*?)["']\)\);?/;

const entrypointPlugin = isWatch => ({
  name: "entrypoint-plugin",
  setup(build) {
    build.onLoad({ filter: /app\/javascript\/packs\/\w+\.js/ }, async args => {
      const fs = require("fs").promises;
      const contents = await fs.readFile(args.path, "utf8");

      const eventSrcCode = `new EventSource("http://localhost:${
        process.env.DEVSERVER_PORT || 8000
      }/esbuild").addEventListener('change', () => location.reload());`;

      const contentsWithEventSource = isWatch
        ? `${eventSrcCode}\n${contents}`
        : contents;

      const lazyLoadImport = contents.match(LAZY_LOAD_IMPORT);
      const componentContext = contents.match(COMPONENT_CONTEXT);
      if (lazyLoadImport && componentContext) {
        const componentName = lazyLoadImport[1];
        const importPath = lazyLoadImport[2];
        const updatedContext = `const componentsContext = { ${componentName}: require("${importPath}").default };`;

        const transformedContents = contentsWithEventSource
          .replace(LAZY_LOAD_IMPORT, "")
          .replace(COMPONENT_CONTEXT, updatedContext);

        return { contents: transformedContents, loader: "js" };
      }

      return { contents: contentsWithEventSource, loader: "js" };
    });
  },
});

module.exports = { entrypointPlugin };
