import { createContext, memo, useContext, useEffect, useMemo, useState } from "react"
import texts from "./texts.yml"

type Keys = keyof typeof texts

const ALLOWED = new Set(["en", "fr"])
const LOCALSTORAGE_KEY = "preferred-locale"

function getLocaleFromStorage() {
  try {
    const key = localStorage.getItem(LOCALSTORAGE_KEY)
    if (key && ALLOWED.has(key)) {
      return key
    }
  } catch {}
}

function getNavigatorLocale() {
  if (typeof navigator !== "undefined") {
    for (const lang of navigator.languages) {
      if (ALLOWED.has(lang)) {
        return lang
      }
    }
  }
}

function getEnvLocale() {
  return getLocaleFromStorage() ?? getNavigatorLocale() ?? "en"
}

const LocaleContext = createContext<{
  locale: string
  setLocale(locale: string): void
}>(undefined!)

export const useLocaleContext = () => useContext(LocaleContext)

export function useTranslate() {
  const { locale } = useContext(LocaleContext)
  const t = useMemo(
    () =>
      new Proxy(
        {},
        {
          get(_, p: string) {
            if (
              process.env.NODE_ENV === "development" &&
              !Object.prototype.hasOwnProperty.call(texts, p)
            ) {
              throw new Error(`t.${p} does not exist.`)
            }
            return (texts as any)[p][locale]
          },
        }
      ) as {
        [key in Keys]: string
      },
    [locale]
  )
  return t
}

export const LocaleContextProvider = memo(({ children }) => {
  const [locale, setLocale] = useState(getEnvLocale)
  useEffect(() => {
    try {
      localStorage.setItem(LOCALSTORAGE_KEY, locale)
    } catch {}
  }, [locale])
  const value = useMemo(() => ({ locale, setLocale }), [locale])
  return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
})
