import I18n from "i18n-js";
import { createContext, useCallback, useContext, useEffect } from "react";

import type { IFormError } from "@greatness/components/src/form/Form";
import translationsEn from "@/i18n/en.json";

const Language = {
  EN: "EN",
};

const defaultLocale = Language.EN;

I18n.fallbacks = false;
I18n.defaultLocale = defaultLocale;
I18n.locale = defaultLocale;
I18n.translations = {
  [Language.EN]: translationsEn,
};

type TranslateFunction<T = string> = (
  translationKey: string,
  translateOptions?: Record<string, number | string>,
) => T;
type IntlProviderState = {
  locale: string;
  t: TranslateFunction;
};

const DEFAULT_STATE: IntlProviderState = {
  locale: defaultLocale,
  t: () => "",
};

const I18nContext = createContext(DEFAULT_STATE);
export const useIntl = (): IntlProviderState => useContext(I18nContext);

export default function IntlProvider({ children }: React.PropsWithChildren) {
  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation> good
  const translate: TranslateFunction = useCallback(
    (translationKey, translateOptions) => {
      const translated = I18n.t(translationKey, translateOptions);
      if (translationKey === "") {
        throw new Error("Invalid translator");
      }
      return typeof translated === "string" && translated.includes("[missing")
        ? ""
        : translated;
    },
    [],
  );

  useEffect(() => {
    I18n.translations[Language.EN] = translationsEn;
  }, []);

  return (
    <I18nContext.Provider
      value={{
        // @todo language switching
        locale: DEFAULT_STATE.locale,
        t: translate,
      }}
    >
      {children}
    </I18nContext.Provider>
  );
}

export const getTranslatedError = (
  t: TranslateFunction,
  error?: IFormError,
): string | undefined => {
  if (error) {
    switch (error.type) {
      case "email":
        return t("field.validation.invalidEmail");
      case "min":
      case "max":
      case "required":
        return t("field.validation.required");
      default:
        break;
    }
    if (error.message) {
      return error.type === "manual" ? error.message : t(error.message);
    }
  }
  return undefined;
};
