const fs = require("fs");
const path = require("path");

const { mergeDeepLeft } = require("ramda");

const getPkgTransPath = pkg => {
  const packageDir = path.join(__dirname, "../../..");

  const basePath = path.join(packageDir, pkg);
  const transPath1 = path.join(basePath, "app/javascript/src/translations");
  const transPath2 = path.join(basePath, "src/translations");

  return fs.existsSync(transPath1) ? transPath1 : transPath2;
};

const loadTranslations = translationsDir => {
  try {
    const jsonFiles = fs
      .readdirSync(translationsDir)
      .filter(file => file.endsWith(".json"))
      .map(file => path.join(translationsDir, file));

    const translations = {};

    jsonFiles.forEach(jsonFile => {
      const content = fs.readFileSync(jsonFile, "utf8");
      const basename = path.basename(jsonFile, ".json");
      translations[basename] = { translation: JSON.parse(content) };
    });

    return translations;
  } catch {
    return {};
  }
};

const generatePackageTranslations = () => {
  const packageDir = "./node_modules/@bigbinary";
  const packages = fs.readdirSync(packageDir);

  return packages
    .map(pkg => {
      const transPath = getPkgTransPath(pkg);

      return fs.existsSync(transPath) ? loadTranslations(transPath) : {};
    })
    .reduce(mergeDeepLeft, {});
};

const getHostTranslations = () => {
  const transPath1 = "./app/javascript/src/translations";
  const transPath2 = "./src/translations";

  if (fs.existsSync(transPath1)) return loadTranslations(transPath1);

  if (fs.existsSync(transPath2)) return loadTranslations(transPath2);

  return {};
};

const generateMergedTranslations = () => {
  const packageTranslations = generatePackageTranslations();
  const hostTranslations = getHostTranslations();
  const supportedLanguages = Object.keys(hostTranslations);

  const filteredPackageTranslations = Object.fromEntries(
    Object.entries(packageTranslations).filter(([lang]) =>
      supportedLanguages.includes(lang)
    )
  );

  return mergeDeepLeft(hostTranslations, filteredPackageTranslations);
};

const writeTranslationsToDisk = mergedTranslations => {
  const publicTranslationsDir = path.join(
    process.cwd(),
    "dist",
    "translations"
  );

  if (!fs.existsSync(publicTranslationsDir)) {
    fs.mkdirSync(publicTranslationsDir, { recursive: true });
  }

  Object.keys(mergedTranslations).forEach(lang => {
    const translationData = mergedTranslations[lang];
    const outputPath = path.join(publicTranslationsDir, `${lang}.json`);

    fs.writeFileSync(
      outputPath,
      JSON.stringify(translationData.translation, null, 2)
    );
  });
};

module.exports = {
  generateMergedTranslations,
  writeTranslationsToDisk,
};
