import { writeFileSync, readdirSync, lstatSync } from 'fs';
import { join, resolve } from 'path';
import algoliasearch from 'algoliasearch';
import i18n from 'i18next';
import backend from 'i18next-fs-backend';

import {
  algoliaAppId,
  algoliaAPIKey,
  clientLocale,
  environment
} from '../config/env.json';
import { newsIndex } from '../src/utils/algolia-locale-setup';
import { i18nextCodes } from '@freecodecamp/shared/config/i18n';

const i18nextCode = i18nextCodes[clientLocale as keyof typeof i18nextCodes];

i18n
  .use(backend)
  .init({
    defaultNS: 'translations',
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false
    },
    initImmediate: false,
    preload: readdirSync(join(__dirname, '../i18n/locales')).filter(
      fileName => {
        const joinedPath = join(join(__dirname, '../i18n/locales'), fileName);
        const isDirectory = lstatSync(joinedPath).isDirectory();
        return isDirectory;
      }
    ),
    lng: i18nextCode,
    ns: ['translations'],
    backend: {
      loadPath: resolve(
        __dirname,
        `../i18n/locales/${clientLocale}/translations.json`
      )
    }
  })
  .catch((error: Error) => {
    throw Error(error.message);
  });

const t = i18n.t.bind(i18n);

export const roundDownToNearestHundred = (num: number) =>
  Math.floor(num / 100) * 100;

export const convertToLocalizedString = (num: number, ISOCode: string) =>
  num.toLocaleString(ISOCode);

interface GenerateSearchPlaceholderOptions {
  locale?: string;
  mockRecordsNum?: number;
}

export const generateSearchPlaceholder = async (
  options: GenerateSearchPlaceholderOptions = {}
) => {
  const { locale, mockRecordsNum } = options;
  let placeholderText = t('search.placeholder.default');

  try {
    let totalRecords = mockRecordsNum || 0;
    if (!mockRecordsNum) {
      const algoliaClient = algoliasearch(algoliaAppId, algoliaAPIKey);
      const index = algoliaClient.initIndex(newsIndex);
      const res = await index.search('');
      totalRecords = res.nbHits;
    }
    const roundedTotalRecords = roundDownToNearestHundred(totalRecords);

    if (roundedTotalRecords >= 100) {
      placeholderText = i18n.t('search.placeholder.numbered', {
        roundedTotalRecords: convertToLocalizedString(
          roundedTotalRecords,
          i18nextCode
        )
      });
    }
  } catch (_err) {
    if (environment === 'production') {
      console.warn(`
  ----------------------------------------------------------
  Warning: Could not get the total number of Algolia records
  ----------------------------------------------------------
  Make sure that Algolia keys and index are set up correctly.

  Falling back to the default search placeholder text.
  ----------------------------------------------------------
`);
    }
  }

  writeFileSync(
    resolve(
      __dirname,
      `../i18n/locales/${locale ? locale : clientLocale}/search-bar.json`
    ),
    JSON.stringify({
      placeholder: placeholderText
    })
  );

  return placeholderText; // for testing
};

void generateSearchPlaceholder();
// TODO: remove the need to fallback to english once we're confident it's
// unnecessary (client/i18n/config.js will need all references to 'en' removing)
if (clientLocale !== 'english')
  void generateSearchPlaceholder({ locale: 'english' });
