import { DEFAULT_LOCALE } from "@config";
import { partitionBy } from "@utils";
import type { IPage } from "@interfaces/IPage";
import { MDXInstance } from "astro";

const storageKey = "preferredLanguage";

/**
 * This function will look for an existing language preference in
 * localStorage. If there is none, it will guess prefered language
 * from Browser settings. If this doesn't work it will use a default
 * value.
 */
export const getOrGuessInitialLanguageFromBrowser = () => {
  let preferredLanguage = localStorage.getItem(storageKey)?.toLowerCase();
  if (!preferredLanguage) {
    if (/^en\b/.test(navigator.language.toLowerCase())) {
      preferredLanguage = "en";
    } else {
      // Use German as default for unknown language browser settings
      preferredLanguage = DEFAULT_LOCALE;
    }
    localStorage.setItem(storageKey, preferredLanguage);
  }
  return preferredLanguage;
};

export const setLanguage = (newLanguage: string) => {
  localStorage.setItem(storageKey, newLanguage);
};

export const getLanguage = () => {
  return localStorage.getItem(storageKey);
};

export const buildTranslationRoutes = (
  allPages: MDXInstance<IPage>[],
  baseUrl,
  allLocales
) => {
  // Split pages in two, just by the existence of a `translated` frontmatter property
  const [translatedPages, unTranslatedPages] = partitionBy(allPages, (page) =>
    Boolean(page.frontmatter?.translated)
  );

  // The pages w/o the frontmatter property can still be the "translation targets"
  // of another page that has the `translated` property
  const unTranslatedAndNoTargetPages = unTranslatedPages.filter(
    (untranslatedPage) =>
      !translatedPages.some((translatedPage) =>
        untranslatedPage.url.includes(translatedPage.frontmatter.translated)
      )
  );

  const translatedRoutes = translatedPages
    .flatMap((translatedPage) =>
      buildTranslatedRoutesFromPage(translatedPage, baseUrl, allLocales)
    )
    .filter(Boolean);

  const fallbackRoutes = unTranslatedAndNoTargetPages
    .flatMap((untranslatedPage) =>
      buildFallbackRouteForPage(untranslatedPage, baseUrl, allLocales)
    )
    .filter(Boolean);

  return [...translatedRoutes, ...fallbackRoutes];
};

/**
 * Build a fallback route for a given page (this is a route that redirects to the home page, e.g. if no translated content is available)
 */
const buildFallbackRouteForPage = (
  page: MDXInstance<IPage>,
  baseUrl: string,
  allLocales: string[],
  targetOverride?: string
) => {
  const urlPartsWithoutBase = page?.url
    ?.replace(baseUrl, "")
    .split("/")
    .filter(Boolean);

  if (urlPartsWithoutBase && urlPartsWithoutBase.length > 0) {
    const localeFromUrl = urlPartsWithoutBase && urlPartsWithoutBase[0];
    const otherLocale = allLocales.filter(
      (locale) => locale !== localeFromUrl
    )[0];
    const middleParts = urlPartsWithoutBase?.slice(1, -1);
    const slugFromUrl = urlPartsWithoutBase.at(-1);
    const firstRedirect = {
      from: `${otherLocale}${
        Boolean(middleParts.length) ? `/${middleParts?.join("/")}` : ""
      }/${slugFromUrl}`,
      to: targetOverride || "/",
    };
    return [
      {
        params: {
          slug: firstRedirect.from,
        },
        props: {
          newTarget: firstRedirect.to,
        },
      },
    ];
  }
};

/**
 * Build translated routes for a given page. This results in two routes (back and forth)
 */
const buildTranslatedRoutesFromPage = (
  page: MDXInstance<IPage>,
  baseUrl: string,
  allLocales: string[]
) => {
  const urlPartsWithoutBase = page?.url
    ?.replace(baseUrl, "")
    .split("/")
    .filter(Boolean);

  if (urlPartsWithoutBase && urlPartsWithoutBase.length > 0) {
    const localeFromUrl = urlPartsWithoutBase && urlPartsWithoutBase[0];
    const otherLocale = allLocales.filter(
      (locale) => locale !== localeFromUrl
    )[0];
    const middleParts = urlPartsWithoutBase?.slice(1, -1);
    const slugFromUrl = urlPartsWithoutBase.at(-1);

    const otherSlugWithoutLocale = page.frontmatter?.translated
      ?.split("/")
      .filter(Boolean)
      .slice(1)
      .join("/");

    if (otherSlugWithoutLocale) {
      const firstRedirect = {
        from: `${localeFromUrl}/${otherSlugWithoutLocale}`,
        to: page.url,
      };

      const secondRedirect = {
        from: `${otherLocale}${
          Boolean(middleParts.length) ? `/${middleParts?.join("/")}` : ""
        }/${slugFromUrl}`,
        to: `${baseUrl}/${otherLocale}/${otherSlugWithoutLocale}`,
      };

      return [
        {
          params: {
            slug: firstRedirect.from,
          },
          props: {
            newTarget: firstRedirect.to,
          },
        },
        {
          params: {
            slug: secondRedirect.from,
          },
          props: { newTarget: secondRedirect.to },
        },
      ];
    }
  }
};