// (c) 2025 TWWIM UG. All rights reserved.

import { createContext, useContext, useState, useEffect, type ReactNode } from 'react';
import { defaultLocale, isValidLocale, type Locale } from './config';

interface TranslationContextType {
  locale: Locale;
  setLocale: (locale: Locale) => void;
  t: (key: string, variables?: Record<string, string | number>) => string;
}

const TranslationContext = createContext<TranslationContextType | undefined>(undefined);

const STORAGE_KEY = 'archer-locale';

function getInitialLocale(): Locale {
  try {
    const stored = localStorage.getItem(STORAGE_KEY);
    if (stored && isValidLocale(stored)) return stored;
  } catch {
    // SSR or localStorage unavailable
  }
  return defaultLocale;
}

let translationsCache: Record<Locale, Record<string, unknown>> | null = null;

async function loadTranslations(): Promise<Record<Locale, Record<string, unknown>>> {
  if (translationsCache) return translationsCache;
  const [de, en] = await Promise.all([
    import('./translations/de.json'),
    import('./translations/en.json'),
  ]);
  translationsCache = { de: de.default, en: en.default };
  return translationsCache;
}

function resolve(obj: unknown, keys: string[]): string | undefined {
  let current = obj;
  for (const k of keys) {
    if (current == null || typeof current !== 'object') return undefined;
    current = (current as Record<string, unknown>)[k];
  }
  return typeof current === 'string' ? current : undefined;
}

export function TranslationProvider({ children }: { children: ReactNode }) {
  const [locale, setLocaleState] = useState<Locale>(getInitialLocale);
  const [translations, setTranslations] = useState<Record<Locale, Record<string, unknown>> | null>(null);

  useEffect(() => {
    loadTranslations().then(setTranslations);
  }, []);

  const setLocale = (l: Locale) => {
    setLocaleState(l);
    try {
      localStorage.setItem(STORAGE_KEY, l);
    } catch {
      // ignore
    }
  };

  const t = (key: string, variables?: Record<string, string | number>): string => {
    if (!translations) return key;
    const keys = key.split('.');
    let value = resolve(translations[locale], keys);
    // Fallback to other locale
    if (value === undefined) {
      const fallback = locale === 'de' ? 'en' : 'de';
      value = resolve(translations[fallback], keys);
    }
    if (value === undefined) return key;

    if (variables) {
      return value.replace(/\{\{(\w+)\}\}/g, (_match, variable: string) => {
        return variables[variable] != null ? String(variables[variable]) : `{{${variable}}}`;
      });
    }
    return value;
  };

  return (
    <TranslationContext.Provider value={{ locale, setLocale, t }}>
      {children}
    </TranslationContext.Provider>
  );
}

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