'use client';

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useLayoutEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import type { Locale, MessageDict } from './types';
import { documentLocale, getNested, interpolate } from './utils';
import { api, apiPaths } from '@/lib/api';
import { getUser, setUser } from '@/lib/auth';
import messagesAr from '@/messages/ar.json';
import messagesEn from '@/messages/en.json';

const STORAGE_KEY = 'locale';

const dicts: Record<Locale, MessageDict> = {
  ar: messagesAr as MessageDict,
  en: messagesEn as MessageDict,
};

function readInitialLocale(): Locale {
  if (typeof window === 'undefined') return 'ar';
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (raw === 'ar' || raw === 'en') return raw;
  } catch {
    /* ignore */
  }
  const u = getUser();
  if (u?.lang === 'ar' || u?.lang === 'en') return u.lang;
  return 'ar';
}

type I18nContextValue = {
  locale: Locale;
  /** يُحدّث الواجهة ويستدعي الـ API؛ يعيد true عند النجاح */
  setLocale: (next: Locale) => Promise<boolean>;
  t: (key: string, vars?: Record<string, string>) => string;
  isRtl: boolean;
};

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

export function I18nProvider({ children }: { children: ReactNode }) {
  /** أول طلاء متطابق مع SSR (ar)، ثم مزامنة فورية من التخزين قبل أول رسم (لتفادي وميض اللغة) */
  const [locale, setLocaleState] = useState<Locale>('ar');

  useLayoutEffect(() => {
    const next = readInitialLocale();
    setLocaleState(next);
    documentLocale(next);
  }, []);

  useEffect(() => {
    documentLocale(locale);
    try {
      window.localStorage.setItem(STORAGE_KEY, locale);
    } catch {
      /* ignore */
    }
  }, [locale]);

  const messages = dicts[locale] ?? dicts.ar;

  const t = useCallback(
    (key: string, vars?: Record<string, string>) => {
      const raw = getNested(messages, key) ?? key;
      return interpolate(raw, vars);
    },
    [messages]
  );

  const setLocale = useCallback(
    async (next: Locale): Promise<boolean> => {
      if (next !== 'ar' && next !== 'en') return false;
      const previous = locale;
      setLocaleState(next);
      try {
        const res = await api.get<unknown>(apiPaths.general.changeLang(next));
        if (res.key !== 'success') {
          setLocaleState(previous);
          return false;
        }
        const u = getUser();
        if (u) {
          setUser({ ...u, lang: next });
        }
        return true;
      } catch {
        setLocaleState(previous);
        return false;
      }
    },
    [locale]
  );

  const value = useMemo<I18nContextValue>(
    () => ({
      locale,
      setLocale,
      t,
      isRtl: locale === 'ar',
    }),
    [locale, setLocale, t]
  );

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

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

/** للاستخدام داخل مكوّنات قد تُحمَّل خارج الـ Provider (يجب عدم حدوث ذلك). */
export function useI18nOptional(): I18nContextValue | null {
  return useContext(I18nContext);
}
