import { useCallback, useEffect, useRef, useState } from "react";
import { languagesData } from "../components/header/languages";

const LANGUAGE_CHANGED_EVENT = "learngual:language-changed";
const DEFAULT_LANGUAGE = "en";
const supportedLanguageSlugs = languagesData.map((language) => language.slug);

// Globals cache for master translations
if (!window.translationCache) {
  window.translationCache = {};
}

if (!window.translationCache._inflight) {
  window.translationCache._inflight = {};
}

//updated lang
const environment =
  window.location.hostname.includes("staging") ||
  window.location.hostname.includes("localhost") ||
  window.location.hostname.includes("demo-test-01")
    ? "learngual-bucket"
    : "learngual-production";
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour in milliseconds
const S3_BASE_URL = `https://${environment}.sfo3.digitaloceanspaces.com/${environment}/media/media/translations/`;
const normalizeLanguage = (language = DEFAULT_LANGUAGE) =>
  String(language || DEFAULT_LANGUAGE).trim().toLowerCase();
const normalizeStoredLanguage = (language) => String(language || "").trim().toLowerCase();
const getLanguageCode = (language = "en") =>
  normalizeLanguage(language).toUpperCase();
const isSupportedLanguage = (language) =>
  supportedLanguageSlugs.includes(normalizeStoredLanguage(language));
const getNavigatorLanguage = () => {
  if (typeof navigator === "undefined") {
    return DEFAULT_LANGUAGE;
  }

  return normalizeLanguage(navigator.language || DEFAULT_LANGUAGE).slice(0, 2);
};
export const resolveSupportedLanguage = (language) => {
  const normalizedLanguage = normalizeStoredLanguage(language);

  return isSupportedLanguage(normalizedLanguage)
    ? normalizedLanguage
    : DEFAULT_LANGUAGE;
};
export const getInitialLanguage = () => {
  const storedLanguage = localStorage?.getItem("defaultLang");

  if (isSupportedLanguage(storedLanguage)) {
    return normalizeStoredLanguage(storedLanguage);
  }

  const browserLanguage = getNavigatorLanguage();

  return isSupportedLanguage(browserLanguage)
    ? browserLanguage
    : DEFAULT_LANGUAGE;
};
const syncStoredLanguage = (language) => {
  const resolvedLanguage = resolveSupportedLanguage(language);
  localStorage.setItem("defaultLang", resolvedLanguage);

  return resolvedLanguage;
};

const useTranslation = (initialSentences = []) => {
  const [defaultLang, setDefaultLangState] = useState(() =>
    syncStoredLanguage(getInitialLanguage()),
  );
  const [renderLang, setRenderLang] = useState("en");
  const [isTranslationsLoading, setIsTranslationsLoading] = useState(false);
  const masterRef = useRef(null);
  const renderLangRef = useRef("en");
  const requestIdRef = useRef(0);

  useEffect(() => {
    renderLangRef.current = renderLang;
  }, [renderLang]);

  const setDefaultLang = useCallback((nextLanguage) => {
    const normalizedLanguage = syncStoredLanguage(nextLanguage);

    window.dispatchEvent(
      new CustomEvent(LANGUAGE_CHANGED_EVENT, {
        detail: { language: normalizedLanguage },
      }),
    );
    setDefaultLangState((currentLanguage) =>
      currentLanguage === normalizedLanguage
        ? currentLanguage
        : normalizedLanguage,
    );
  }, []);

  useEffect(() => {
    const handleStorage = (event) => {
      if (event.key !== "defaultLang") {
        return;
      }

      const nextLanguage = syncStoredLanguage(event.newValue);
      setDefaultLangState((currentLanguage) =>
        currentLanguage === nextLanguage ? currentLanguage : nextLanguage,
      );
    };

    const handleLanguageChange = (event) => {
      const nextLanguage = syncStoredLanguage(event?.detail?.language);
      setDefaultLangState((currentLanguage) =>
        currentLanguage === nextLanguage ? currentLanguage : nextLanguage,
      );
    };

    window.addEventListener("storage", handleStorage);
    window.addEventListener(LANGUAGE_CHANGED_EVENT, handleLanguageChange);

    return () => {
      window.removeEventListener("storage", handleStorage);
      window.removeEventListener(LANGUAGE_CHANGED_EVENT, handleLanguageChange);
    };
  }, []);

  /**
    Fetch master translations from S3 with caching
   **/
  const getMasterTranslationsWithCache = async (language) => {
    const now = Date.now();
    const languageCode = getLanguageCode(language);
    const cached = window.translationCache[languageCode];

    // Check if cache is valid and not expired
    if (cached && cached.data && cached.expires > now) {
      return cached.data;
    }

    // If a fetch is already in-flight, reuse it (prevents duplicate requests from StrictMode / concurrent callers)
    if (window.translationCache._inflight[languageCode]) {
      return window.translationCache._inflight[languageCode];
    }

    const fetchPromise = (async () => {
      try {
        const response = await fetch(
          `${S3_BASE_URL}${language?.toUpperCase()}/qFpINMa05DrgUgzO0PEboReejximpq2r3VL2AmFZAwIq6fTN3A.json`,
        );

        if (!response.ok) {
          throw new Error(`Failed to fetch translations: ${response.status}`);
        }

        const masterTranslations = await response.json();

        window.translationCache[languageCode] = {
          data: masterTranslations,
          timestamp: now,
          expires: now + CACHE_DURATION,
        };

        return masterTranslations;
      } catch (error) {
        console.error("Failed to fetch master translations:", error);

        // Fallback to cached data if available (even if expired)
        if (cached && cached.data) {
          return cached.data;
        }

        throw error;
      } finally {
        delete window.translationCache._inflight[languageCode];
      }
    })();

    window.translationCache._inflight[languageCode] = fetchPromise;
    return fetchPromise;
  };

  const findText = useCallback(
    (word, kwargs = {}) => {
      // For English, return the original word directly
      if (renderLang?.toLowerCase() === "en") {
        return formatSentence(word, kwargs);
      }

      const master = masterRef.current;
      if (master && master[word]) {
        const languageCode = getLanguageCode(renderLang);
        const translation = master[word][languageCode];
        if (translation && translation.trim()) {
          return formatSentence(translation.trim(), kwargs);
        }
      }

      // Fallback to original word if translation not found or master not loaded yet
      return formatSentence(word, kwargs);
    },
    [renderLang],
  );

  // Kept for backwards compatibility — no-op
  const handleTranslate = async () => {};

  useEffect(() => {
    const loadMasterTranslations = async () => {
      const selectedLanguage = normalizeLanguage(defaultLang);
      const requestId = requestIdRef.current + 1;
      requestIdRef.current = requestId;

      // Skip fetch for English — findText returns original words directly
      if (selectedLanguage === "en") {
        masterRef.current = null;
        setIsTranslationsLoading(false);
        setRenderLang("en");
        return;
      }

      setIsTranslationsLoading(true);

      try {
        const masterTranslations =
          await getMasterTranslationsWithCache(selectedLanguage);

        if (requestIdRef.current !== requestId) {
          return;
        }

        masterRef.current = masterTranslations;
        setRenderLang(selectedLanguage);
        setIsTranslationsLoading(false);
      } catch (error) {
        if (requestIdRef.current !== requestId) {
          return;
        }

        console.error("Failed to load translations:", error);
        setIsTranslationsLoading(false);
        setRenderLang(renderLangRef.current || "en");
      }
    };

    loadMasterTranslations();
  }, [defaultLang]);

  return {
    defaultLang,
    setDefaultLang,
    handleTranslate,
    translations: {},
    findText,
    isTranslationsLoading,
    setIsTranslationsLoading,
  };
};

export function formatSentence(sentence, kwargs) {
  // console.log(sentence);
  // Use replace with a regular expression and a callback function
  const finalSentence = sentence?.replace(/\{(\w+)\}/g, (match, key) => {
    // If the key exists in kwargs, replace it with the corresponding value
    // Otherwise, keep the original placeholder
    return kwargs[key] !== undefined ? kwargs[key] : match;
  });

  return finalSentence;
}

export default useTranslation;
