import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from 'react';
import type { Translations, LanguageCode } from './types';
import { RTL_LANGUAGES } from './types';
import krd from './translations/krd';
import en from './translations/en';
import tr from './translations/tr';
import ckb from './translations/ckb';
import fa from './translations/fa';
import ar from './translations/ar';

const translations: Record<LanguageCode, Translations> = {
  krd,
  en,
  tr,
  ckb,
  fa,
  ar,
};

// Module-level language tracking for non-React contexts
let currentLanguage: LanguageCode = 'krd';

/**
 * Standalone translate function for non-React files (utils, crypto, error-tracking, etc.)
 * Language is synced from LanguageProvider automatically.
 */
export function translate(key: string, params?: Record<string, string | number>): string {
  let value = getNestedValue(
    translations[currentLanguage] as unknown as Record<string, unknown>,
    key
  );
  if (value === undefined && currentLanguage !== DEFAULT_LANG) {
    value = getNestedValue(translations[DEFAULT_LANG] as unknown as Record<string, unknown>, key);
  }
  if (value === undefined) return key;

  if (params) {
    let result = value;
    for (const [paramKey, paramValue] of Object.entries(params)) {
      result = result.replace(`{${paramKey}}`, String(paramValue));
    }
    return result;
  }

  return value;
}

/** Get current language code (for locale-dependent formatting) */
export function getCurrentLanguage(): LanguageCode {
  return currentLanguage;
}

const VALID_LANGS: LanguageCode[] = ['krd', 'en', 'tr', 'ckb', 'fa', 'ar'];
const DEFAULT_LANG: LanguageCode = 'krd';

/**
 * Map Telegram language codes to our supported languages.
 * Telegram uses IETF codes like "en", "tr", "fa", "ar", "ku".
 */
const TG_LANG_MAP: Record<string, LanguageCode> = {
  ku: 'krd',
  kmr: 'krd',
  ckb: 'ckb',
  tr: 'tr',
  en: 'en',
  fa: 'fa',
  ar: 'ar',
};

/**
 * Detect language priority:
 *   1. URL path (bot sends /tr, /ar — always wins, user just clicked a language button)
 *   2. localStorage (persisted preference from previous session)
 *   3. Telegram WebApp user language (fallback)
 *   4. Default (krd)
 *
 * URL path is consumed once, persisted to localStorage, then cleaned from the URL
 * to prevent Telegram WebView cache issues with #tgWebAppData hash.
 */
function detectLanguage(): LanguageCode {
  // 1. Check URL path FIRST (bot sends /tr, /ar, /en etc.)
  //    This takes priority over localStorage because it represents the user's
  //    active language choice from the bot keyboard.
  const firstSegment = window.location.pathname.split('/').filter(Boolean)[0];
  if (firstSegment && VALID_LANGS.includes(firstSegment as LanguageCode)) {
    localStorage.setItem('app_language', firstSegment);
    window.history.replaceState(null, '', '/' + window.location.search + window.location.hash);
    return firstSegment as LanguageCode;
  }

  // 2. Check localStorage (persisted user preference from previous session)
  const stored = localStorage.getItem('app_language');
  if (stored && VALID_LANGS.includes(stored as LanguageCode)) {
    return stored as LanguageCode;
  }

  // 3. Check Telegram WebApp user language
  try {
    const tg = (
      window as unknown as {
        Telegram?: { WebApp?: { initDataUnsafe?: { user?: { language_code?: string } } } };
      }
    ).Telegram;
    const tgLang = tg?.WebApp?.initDataUnsafe?.user?.language_code;
    if (tgLang) {
      const mapped = TG_LANG_MAP[tgLang];
      if (mapped) {
        localStorage.setItem('app_language', mapped);
        return mapped;
      }
    }
  } catch {
    // Telegram WebApp not available
  }

  return DEFAULT_LANG;
}

/**
 * Get a nested value from an object using dot notation.
 * e.g. getNestedValue(obj, 'nav.forum') -> obj.nav.forum
 */
function getNestedValue(obj: Record<string, unknown>, path: string): string | undefined {
  const keys = path.split('.');
  let current: unknown = obj;
  for (const key of keys) {
    if (current == null || typeof current !== 'object') return undefined;
    current = (current as Record<string, unknown>)[key];
  }
  return typeof current === 'string' ? current : undefined;
}

interface LanguageContextType {
  lang: LanguageCode;
  setLang: (lang: LanguageCode) => void;
  t: (key: string, params?: Record<string, string | number>) => string;
  isRTL: boolean;
}

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

interface LanguageProviderProps {
  children: ReactNode;
}

export function LanguageProvider({ children }: LanguageProviderProps) {
  const [lang, setLangState] = useState<LanguageCode>(detectLanguage);

  const isRTL = RTL_LANGUAGES.includes(lang);

  // Sync module-level language for standalone translate()
  useEffect(() => {
    currentLanguage = lang;
  }, [lang]);

  // Update document direction, lang attribute, and persist to localStorage
  useEffect(() => {
    document.documentElement.lang = lang === 'krd' ? 'ku' : lang;
    document.documentElement.dir = isRTL ? 'rtl' : 'ltr';
    localStorage.setItem('app_language', lang);
  }, [lang, isRTL]);

  const setLang = useCallback((newLang: LanguageCode) => {
    setLangState(newLang);
    localStorage.setItem('app_language', newLang);
  }, []);

  const t = useCallback(
    (key: string, params?: Record<string, string | number>): string => {
      // Try current language first
      let value = getNestedValue(translations[lang] as unknown as Record<string, unknown>, key);
      // Fallback to Kurdish
      if (value === undefined && lang !== DEFAULT_LANG) {
        value = getNestedValue(
          translations[DEFAULT_LANG] as unknown as Record<string, unknown>,
          key
        );
      }
      // If still not found, return the key itself
      if (value === undefined) return key;

      // Replace params like {time}, {count}, {amount}, {rating}
      if (params) {
        let result = value;
        for (const [paramKey, paramValue] of Object.entries(params)) {
          result = result.replace(`{${paramKey}}`, String(paramValue));
        }
        return result;
      }

      return value;
    },
    [lang]
  );

  return (
    <LanguageContext.Provider value={{ lang, setLang, t, isRTL }}>
      {children}
    </LanguageContext.Provider>
  );
}

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

export type { LanguageCode, Translations };
export { VALID_LANGS, DEFAULT_LANG, RTL_LANGUAGES, LANGUAGE_NAMES } from './types';
