'use client';

import {
  createContext,
  useContext,
  useCallback,
  useSyncExternalStore,
  useEffect,
  ReactNode,
  useRef,
} from 'react';
import { Language } from '@/lib/translations/dealer-template';

interface LanguageContextValue {
  language: Language;
  setLanguage: (lang: Language) => void;
}

const LanguageContext = createContext<LanguageContextValue | null>(null);

interface LanguageProviderProps {
  defaultLanguage: Language;
  subdomain: string;
  children: ReactNode;
}

/**
 * Read language preference from cookie or sessionStorage.
 */
function getStoredLanguage(storageKey: string, fallback: Language): Language {
  // Check cookie first (more reliable across page loads)
  const cookies = document.cookie.split(';');
  const langCookie = cookies.find((c) => c.trim().startsWith(`${storageKey}=`));
  if (langCookie) {
    const value = langCookie.split('=')[1]?.trim();
    if (value === 'en' || value === 'es' || value === 'fr') {
      return value;
    }
  }
  // Fall back to sessionStorage
  const saved = sessionStorage.getItem(storageKey);
  if (saved === 'en' || saved === 'es' || saved === 'fr') {
    return saved;
  }
  return fallback;
}

/**
 * Provides language state for dealer template.
 *
 * Language is stored in cookie and sessionStorage per subdomain so:
 * - Choice persists across page loads (cookie for server, sessionStorage for client)
 * - Different dealers can have different language choices
 * - Server can read cookie to prevent flash on dynamic pages
 */
export function LanguageProvider({ defaultLanguage, subdomain, children }: LanguageProviderProps) {
  const storageKey = `dlp-lang-${subdomain}`;

  // Use ref to hold listeners for useSyncExternalStore
  const listenersRef = useRef(new Set<() => void>());

  // Subscribe function for useSyncExternalStore
  const subscribe = useCallback((listener: () => void) => {
    listenersRef.current.add(listener);
    return () => listenersRef.current.delete(listener);
  }, []);

  // Get snapshot from external storage (client-side)
  const getSnapshot = useCallback(
    () => getStoredLanguage(storageKey, defaultLanguage),
    [storageKey, defaultLanguage]
  );

  // Server snapshot always returns defaultLanguage
  const getServerSnapshot = useCallback(() => defaultLanguage, [defaultLanguage]);

  // Use useSyncExternalStore for hydration-safe external state
  const language = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);

  // Update HTML lang attribute for accessibility and SEO
  useEffect(() => {
    document.documentElement.lang = language;
  }, [language]);

  // Persist language changes and notify listeners
  const setLanguage = useCallback(
    (lang: Language) => {
      sessionStorage.setItem(storageKey, lang);
      // Set cookie for server-side reading (prevents flash on refresh)
      // Max-age: 1 year, SameSite=Lax for security
      document.cookie = `${storageKey}=${lang}; path=/; max-age=31536000; SameSite=Lax`;
      // Notify all listeners to trigger re-render
      listenersRef.current.forEach((listener) => listener());
    },
    [storageKey]
  );

  return (
    <LanguageContext.Provider value={{ language, setLanguage }}>
      {children}
    </LanguageContext.Provider>
  );
}

/**
 * Hook to access language context.
 * Must be used within a LanguageProvider.
 */
export function useLanguage(): LanguageContextValue {
  const context = useContext(LanguageContext);
  if (!context) {
    throw new Error('useLanguage must be used within a LanguageProvider');
  }
  return context;
}
