import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
import {
  DEFAULT_EXTERNAL_LOCALE,
  EXTERNAL_LANGUAGE_OPTIONS,
  EXTERNAL_LOCALE_STORAGE_KEY,
  externalDirection,
  externalMessage,
  normalizeExternalLocale
} from "./messages.js";

const defaultTranslate = (key, values) => interpolate(externalMessage(DEFAULT_EXTERNAL_LOCALE, key), values);
const ExternalI18nContext = createContext({
  direction: "ltr",
  languages: EXTERNAL_LANGUAGE_OPTIONS,
  locale: DEFAULT_EXTERNAL_LOCALE,
  setLocale: () => {},
  t: defaultTranslate
});

export function ExternalI18nProvider({ children }) {
  // The product default is deliberately English. Browser language is ignored until the operator explicitly chooses and persists another locale.
  const [locale, setLocaleState] = useState(readPersistedLocale);
  const direction = externalDirection(locale);
  const setLocale = useCallback((nextLocale) => {
    const normalized = normalizeExternalLocale(nextLocale);
    setLocaleState(normalized);
    try {
      globalThis.localStorage?.setItem(EXTERNAL_LOCALE_STORAGE_KEY, normalized);
    } catch {
      // Storage can be unavailable in hardened/private browser contexts; the in-memory locale still changes for the current session.
    }
  }, []);
  const t = useCallback((key, values) => interpolate(externalMessage(locale, key), values), [locale]);

  useEffect(() => {
    // Keep native controls, assistive technology, MUI portals and the shell aligned when Arabic changes writing direction.
    const root = globalThis.document?.documentElement;
    if (!root) {
      return;
    }
    root.lang = locale;
    root.dir = direction;
    globalThis.document.body?.setAttribute("dir", direction);
  }, [direction, locale, t]);

  const value = useMemo(
    () => ({ direction, languages: EXTERNAL_LANGUAGE_OPTIONS, locale, setLocale, t }),
    [direction, locale, setLocale, t]
  );

  return <ExternalI18nContext.Provider value={value}>{children}</ExternalI18nContext.Provider>;
}

export function useExternalI18n() {
  return useContext(ExternalI18nContext);
}

function readPersistedLocale() {
  try {
    return normalizeExternalLocale(globalThis.localStorage?.getItem(EXTERNAL_LOCALE_STORAGE_KEY));
  } catch {
    return DEFAULT_EXTERNAL_LOCALE;
  }
}

function interpolate(message, values = {}) {
  return String(message).replace(/\{(\w+)\}/g, (match, key) => (values[key] === undefined ? match : String(values[key])));
}
