"use client";

import {
  createContext,
  useCallback,
  useContext,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import { useRouter } from "next/navigation";
import { useQueryClient } from "@tanstack/react-query";
import type { Dictionary } from "./dictionaries/dictionary.type";
import { createTranslationEngine, type TranslationEngine } from "./engine";
import { setLanguageCookie } from "./cookie";
import type { Language } from "./config";
import en from "./dictionaries/en.json";
import ar from "./dictionaries/ar.json";

// Both dictionaries are tiny (a few KB) and needed on the client to switch
// languages without a reload, so they're bundled statically — selecting one is a
// synchronous, instant lookup (no async load / cache / preload machinery).
const dictionaries: Record<Language, Dictionary> = { en, ar };

interface I18nContextType extends TranslationEngine {
  language: Language;
  isRTL: boolean;
  setLanguage: (language: Language) => void;
}

const I18nContext = createContext<I18nContextType | null>(null);

interface I18nProviderProps {
  children: ReactNode;
  initialLanguage: Language;
}

export function I18nProvider({ children, initialLanguage }: I18nProviderProps) {
  const router = useRouter();
  const queryClient = useQueryClient();

  // The NEXT_LANG cookie is the single source of truth. The server reads it and
  // forwards it as `initialLanguage`; the client seeds state from that ONCE and
  // never re-derives it — that's what keeps reload/new-tab renders flash-free.
  const [language, setLanguageState] = useState<Language>(
    () => initialLanguage,
  );
  const isRTL = language === "ar";

  const setLanguage = useCallback(
    (next: Language) => {
      if (next === language) return;

      // 1. Flip the client UI immediately (all t() text re-renders via context).
      setLanguageState(next);
      // 2. Apply dir/lang on <html> synchronously so RTL⇄LTR flips together with
      //    the text — waiting for the refresh would briefly render Arabic as LTR.
      if (typeof document !== "undefined") {
        document.documentElement.lang = next;
        document.documentElement.dir = next === "ar" ? "rtl" : "ltr";
      }
      // 3. Persist to the cookie so the next server render (incl. the refresh below) is authoritative.
      setLanguageCookie(next);
      // 4. Refetch the on-screen (active) queries in the background — data stays
      //    visible and comes back with the new x-language header — and drop every
      //    inactive query so it refetches fresh on next visit. Because the client
      //    disables refetchOnMount, "keep stale data" would otherwise show
      //    old-language data on already-visited routes; removing it forces a fetch.
      queryClient.invalidateQueries({ refetchType: "active" });
      queryClient.removeQueries({ type: "inactive" });
      // 5. Soft-refresh Server Components against the updated cookie. No full reload.
      router.refresh();
    },
    [language, queryClient, router],
  );

  const engine = useMemo(
    () => createTranslationEngine(dictionaries[language]),
    [language],
  );

  const value = useMemo<I18nContextType>(
    () => ({ ...engine, language, isRTL, setLanguage }),
    [engine, language, isRTL, setLanguage],
  );

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

export function useI18n(): I18nContextType {
  const context = useContext(I18nContext);
  if (!context) throw new Error("useI18n must be used within I18nProvider");
  return context;
}
