import fs from "fs";
import { createRequire } from "node:module";
import path from "path";
import { fileURLToPath } from "url";

import { mergeDeepLeft, mergeLeft, keys } from "ramda";

const require = createRequire(import.meta.url);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const loadJS = jsPath => {
  try {
    return require(jsPath);
  } catch {
    return {};
  }
};

const doesFileExist = filePath =>
  fs.existsSync(filePath) && fs.lstatSync(filePath).isFile();

const generateAllPathsInsideDir = dirPath => {
  const files = fs.readdirSync(dirPath, { withFileTypes: true });

  return files.flatMap(file => {
    const filePath = path.join(dirPath, file.name);

    return file.isDirectory() ? generateAllPathsInsideDir(filePath) : filePath;
  });
};

const generatePathGroupsFromAssets = assetsPath => {
  if (!fs.existsSync(assetsPath)) return [];

  return generateAllPathsInsideDir(assetsPath).map(absPath => ({
    pattern: absPath.replace(assetsPath, "").split(".")[0],
    group: "internal",
  }));
};

const buildPathGroupsBasedOnWebpackAliases = ({
  customAliasPath = "config/esbuild/config.js",
  commonAliasPath = "node_modules/@bigbinary/neeto-commons-frontend/configs/webpack/resolve.js",
}) => {
  const rootOfProject = path.join(__dirname, "../../../../../../");
  const projectResolve = loadJS(path.join(rootOfProject, customAliasPath));
  const commonResolve = loadJS(path.join(rootOfProject, commonAliasPath));

  const { dependencies = [], devDependencies = [] } = loadJS(
    path.join(rootOfProject, "package.json")
  );
  const packages = keys(mergeLeft(dependencies, devDependencies));
  const { alias = {}, extensions = [] } = mergeDeepLeft(
    projectResolve,
    commonResolve
  );

  const pathGroups = Object.entries(alias).flatMap(([pattern, aliasPath]) => {
    const group = packages.includes(aliasPath) ? "external" : "internal";
    const isFile = ["", ...extensions].some(extension =>
      doesFileExist(`${aliasPath}${extension}`)
    );

    if (isFile) return { pattern, group };

    return [
      { pattern, group },
      { pattern: `${pattern}/**`, group },
    ];
  });

  const pathGroupsFromAssets = generatePathGroupsFromAssets(
    path.join(rootOfProject, "app/assets/")
  );

  return pathGroups.concat(pathGroupsFromAssets);
};

export default { buildPathGroupsBasedOnWebpackAliases };
