import React, { createContext, useCallback, useContext, useEffect } from "react";

import { useSessionStorage } from "../hooks/useStorage";

import { useApi } from "./ApiContext";

export function interpolateString(
  string: string,
  params: Record<string, string> | string[],
): string {
  return Array.isArray(params)
    ? params.reduce((s, value) => s?.replace(/%[sd]|\{\}/, value), string)
    : Object.entries(params).reduce(
        (s, [key, value]) => s?.replace(new RegExp(`%\\(${key}\\)[sd]|\\{${key}\\}`, "g"), value),
        string,
      );
}

export interface I18nContext {
  i18n: Record<string, string> | undefined;
  t: (key: string, params?: Record<string, string> | string[]) => string;
}

const I18nContext = createContext<I18nContext>(undefined as unknown as I18nContext);
export const useI18n = () => useContext(I18nContext);

export const I18nContextProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
  const api = useApi();
  const [i18n, setI18n] = useSessionStorage<Record<string, string> | undefined>("i18n", undefined);

  useEffect(() => {
    if (api && i18n == null) {
      api.operations["bananas.i18n:list"].call().then(async (response) => {
        const i18n = (await response.json()).catalog;
        setI18n(i18n);
      });
    }
  }, [api, i18n]);

  const t = useCallback(
    (key: string, params?: Record<string, string> | string[] | null | undefined) => {
      const value = i18n?.[key] ?? key;
      return params ? interpolateString(value, params) : value;
    },
    [i18n],
  );

  return <I18nContext.Provider value={{ i18n, t }}>{children}</I18nContext.Provider>;
};

export default I18nContext;
