import {
  createContext,
  useContext,
  useState,
  useEffect,
  useCallback,
  useMemo,
  useRef,
} from 'react';
import {
  initTranslations,
  loadTranslationWithFallback,
  getLoadedTranslation,
} from 'lib/translations';
import variables from 'config/variables';
import EventBus from 'utils/eventbus';

const RTL_LANGUAGES = ['ar', 'arz', 'azb', 'fa', 'peo'];
const isRTLLanguage = (lang) => RTL_LANGUAGES.includes(lang.split('_')[0]);

const TranslationContext = createContext();

export function TranslationProvider({ children, initialLanguage, initialTranslations }) {
  const [currentLanguage, setCurrentLanguage] = useState(initialLanguage);
  const [isLoading, setIsLoading] = useState(false);
  const i18nInstance = useRef(initTranslations(initialLanguage, initialTranslations));

  useEffect(() => {
    variables.language = i18nInstance.current;
    variables.languagecode = currentLanguage;
    document.documentElement.lang = currentLanguage.replace('_', '-');
    document.documentElement.dir = isRTLLanguage(currentLanguage) ? 'rtl' : 'ltr';
  }, [currentLanguage]);

  const changeLanguage = useCallback(
    async (newLanguage) => {
      setIsLoading(true);
      try {
        const translations = await loadTranslationWithFallback(newLanguage);
        const newI18n = initTranslations(newLanguage, translations);

        const currentTabName = localStorage.getItem('tabName');
        const oldDefaultTabName = i18nInstance.current?.getMessage(currentLanguage, 'tabname');

        i18nInstance.current = newI18n;
        variables.language = newI18n;
        variables.languagecode = newLanguage;
        document.documentElement.lang = newLanguage.replace('_', '-');
        document.documentElement.dir = isRTLLanguage(newLanguage) ? 'rtl' : 'ltr';

        if (currentTabName === oldDefaultTabName || !currentTabName) {
          const loadedTranslation = getLoadedTranslation(newLanguage);
          const newTabName =
            loadedTranslation?.tabname || newI18n.getMessage(newLanguage, 'tabname') || 'Mue';
          localStorage.setItem('tabName', newTabName);
          document.title = newTabName;
        }

        localStorage.setItem('language', newLanguage);
        localStorage.removeItem('currentWeather');

        setCurrentLanguage(newLanguage);
      } catch (error) {
        console.error('Failed to load language:', error);
      } finally {
        setIsLoading(false);
      }
    },
    [currentLanguage],
  );

  const t = useCallback(
    (key, optional = {}) => {
      if (!i18nInstance.current) {
        return key;
      }
      try {
        return i18nInstance.current.getMessage(currentLanguage, key, optional);
      } catch (error) {
        // Fallback to en_GB if the current language is not loaded yet
        try {
          return i18nInstance.current.getMessage('en_GB', key, optional);
        } catch {
          return key;
        }
      }
    },
    [currentLanguage],
  );

  useEffect(() => {
    const handleLanguageChange = (data) => {
      if (data?.language) {
        changeLanguage(data.language);
      }
    };

    EventBus.on('languageChange', handleLanguageChange);

    return () => {
      EventBus.off('languageChange', handleLanguageChange);
    };
  }, [changeLanguage]);

  useEffect(() => {
    variables.getMessage = (key, optional = {}) => t(key, optional);
  }, [t]);

  const value = useMemo(
    () => ({
      language: currentLanguage,
      languagecode: currentLanguage,
      changeLanguage,
      isLoading,
      t,
    }),
    [currentLanguage, changeLanguage, isLoading, t],
  );

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

export function useTranslation() {
  const context = useContext(TranslationContext);
  if (!context) {
    throw new Error('useTranslation must be used within a TranslationProvider');
  }
  return context;
}

export function useT() {
  const { t } = useTranslation();
  return t;
}
