import { readFileSync, writeFileSync } from 'fs';

import readStrings from '../src/util/data/readStrings';

const TOP_COMMENT = '// This file is generated by dev/generateLangTypes.ts. Do not edit it manually.\n';
const LANG_KEY_TYPE = `
export type RegularLangKey = keyof LangPair;
export type RegularLangKeyWithVariables = keyof LangPairWithVariables;
export type PluralLangKey = keyof LangPairPlural;
export type PluralLangKeyWithVariables = keyof LangPairPluralWithVariables;
export type LangKey = RegularLangKey | RegularLangKeyWithVariables | PluralLangKey | PluralLangKeyWithVariables;
type LangVariable = string | number | undefined;
`.trim();

const data = readFileSync('./src/assets/localization/fallback.strings', 'utf8');

const parsed = readStrings(data);
const regularKeysWithVars: Record<string, string[]> = {};
const pluralKeysWithVars: Record<string, string[]> = {};
Object.entries(parsed).forEach(([keyWithSuffix, value]) => {
  const [key, pluralSuffix] = keyWithSuffix.split('_');
  const variables = extractVariables(value);

  const acc = pluralSuffix ? pluralKeysWithVars : regularKeysWithVars;

  const previousVariables = acc[key] || [];
  previousVariables.push(...variables);
  acc[key] = previousVariables;
});

const regularTypes = formatKeyWithVariables(false, regularKeysWithVars);
const pluralTypes = formatKeyWithVariables(true, pluralKeysWithVars);

const text = `${TOP_COMMENT}\n${regularTypes}\n${pluralTypes}${LANG_KEY_TYPE}\n`;
writeFileSync('./src/types/language.d.ts', text, 'utf8');

// eslint-disable-next-line no-console
console.log(`Language types generated
${Object.keys(regularKeysWithVars).length} simple keys
${Object.keys(pluralKeysWithVars).length} plural keys
`);

function extractVariables(value: string) {
  const matches = value.match(/(?<!\\){[^{}]+}/g);
  if (!matches) return [];
  return matches.map((match) => match.slice(1, -1));
}

function wrapInQuotes(value: string) {
  return `'${value}'`;
}

function formatKeyWithVariables(isPlural: boolean, keysWithVars: Record<string, string[]>) {
  let entries = '';
  let variableEntries = '';

  Object.entries(keysWithVars).forEach(([key, variables]) => {
    const uniqueVariables = variables.length ? Array.from(new Set(variables)) : undefined;
    if (uniqueVariables) {
      const type = `{\n    ${uniqueVariables.map((v) => `${wrapInQuotes(v)}: V;`).join('\n    ')}\n  };\n`;
      variableEntries += `  ${wrapInQuotes(key)}: ${type}`;
    } else {
      entries += `  ${wrapInQuotes(key)}: undefined;\n`;
    }
  });

  const typeName = isPlural ? 'LangPairPlural' : 'LangPair';

  return `export interface ${typeName} {\n${entries}}\n
export interface ${typeName}WithVariables<V = LangVariable> {\n${variableEntries}}\n`;
}
