/**
 * i18n-aggregator.ts
 *
 * Aggregates translation files that match a list of prefixes.
 *
 */

import { promises as fs } from "fs";
import * as path from "path";
import { factorioPath, scriptOutputPath } from "./file.helper.ts";
import { dumpFactorioLocale } from "./command.helper.ts";

type Translations = Record<string, Record<string, unknown>>;
export const LOCALE_OF_INTEREST = ["fluid", "item", "recipe", "item-group", "quality", "virtual-signal"];
export const LOCALE_TO_EXPORT = ["en", "ja", "zh-CH", "de", "fr"];

/**
 * Aggregates i18n JSON files that match a list of prefixes and writes a single
 * JSON file containing all translations for the specified i18n code.
 *
 * @param prefixes     Array of file prefixes to look for.  Example: ['app', 'common']
 * @param inputFolder  The folder to search for the locale files.
 * @param outputFolder The folder where the aggregated JSON will be written.
 * @param i18nCode     The i18n code that will be used as the output file name.
 *
 * The function searches `inputFolder` for files that start with one of the
 * provided prefixes and end with `-locale.json`.  Each matching file is
 * parsed as JSON and stored in a `Record<string, any>` where the key is the
 * prefix and the value is the parsed JSON object.  The final aggregated
 * object is written to `outputFolder/i18n/<i18nCode>.json`.
 */
export async function aggregateI18n(
  prefixes: string[],
  inputFolder: string,
  outputFolder: string,
  i18nCode: string
): Promise<void> {
  // Resolve absolute paths
  const inputPath = path.resolve(inputFolder);
  const outputPath = path.resolve(outputFolder, "i18n");

  // Ensure the output directory exists
  await fs.mkdir(outputPath, { recursive: true });

  // Read all files in the input directory
  const allFiles = await fs.readdir(inputPath);

  // Map of prefix => filename
  const prefixToFile: Record<string, string> = {};

  // Find the first file that matches each prefix
  for (const prefix of prefixes) {
    const filename = prefix + "-locale.json";
    const match = allFiles.find((f) => f == filename);
    if (match) {
      prefixToFile[prefix] = match;
    }
  }

  const result: Translations = {};

  // Read and parse each matched file
  for (const [prefix, fileName] of Object.entries(prefixToFile)) {
    const filePath = path.join(inputPath, fileName);
    const data = await fs.readFile(filePath, "utf-8");
    try {
      result[prefix] = JSON.parse(data);
    } catch {
      result[prefix] = {};
    }
  }

  // Write the aggregated JSON to the output folder
  const outputFile = path.join(outputPath, `${i18nCode}.json`);
  await fs.writeFile(outputFile, JSON.stringify(result, null, 2), "utf-8");
}
/**
 * Updates the first `locale=` line in a file to the supplied locale code.
 *
 * @param localCode  New locale code (e.g. "en-US", "de-DE")
 *
 */
export async function setLocaleInIni(localCode: string): Promise<void> {
  const resolvedPath = path.resolve(factorioPath, "config", "config.ini");
  const content = await fs.readFile(resolvedPath, "utf8");
  await fs.writeFile(resolvedPath, content.replace(/^locale=.*$/m, "locale=" + localCode), "utf8");
}

export async function extractLocale(outputFolder: string) {
  for (let i18nCode of LOCALE_TO_EXPORT) {
    console.log("Export i18n for " + i18nCode);
    await setLocaleInIni(i18nCode);
    await dumpFactorioLocale();
    await aggregateI18n(LOCALE_OF_INTEREST, scriptOutputPath, outputFolder, i18nCode);
  }
}
