import React, { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { Language, TranslationKeys, loadLanguage, fetchAvailableLanguageCodes, I18nCodeInfo } from '../../locales';
import { getUserDataCache } from '../../utils/userCache';


export type { Language };

type TranslateParams = Record<string, string | number | boolean | null | undefined>;

interface LanguageContextType {
    currentLanguage: Language;
    setLanguage: (language: Language) => void;
    t: (key: string, paramsOrFallback?: TranslateParams | string) => string;
    isLoading: boolean;
    reloadLanguage: () => Promise<void>;
    availableLanguages: I18nCodeInfo[];
    refreshAvailableLanguages: () => Promise<void>;
}

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

interface LanguageProviderProps {
    children: ReactNode;
}

export const LanguageProvider: React.FC<LanguageProviderProps> = ({ children }) => {
    const [currentLanguage, setCurrentLanguage] = useState<Language>('de');
    const [translations, setTranslations] = useState<TranslationKeys>({});
    const [deTranslations, setDeTranslations] = useState<TranslationKeys>({});
    const [isLoading, setIsLoading] = useState(true);
    const [availableLanguages, setAvailableLanguages] = useState<I18nCodeInfo[]>([]);

    // Function to load and set a language
    const loadAndSetLanguage = async (language: Language) => {
        setIsLoading(true);
        try {
            const deKeys = await loadLanguage('de');
            setDeTranslations(deKeys);
            const targetKeys =
                language === 'de' ? deKeys : await loadLanguage(language);
            setTranslations(targetKeys);
            setCurrentLanguage(language);
        } catch (error) {
            console.error('Failed to load language:', error);
            // Keep current language and translations if loading fails
        } finally {
            setIsLoading(false);
        }
    };

    // Load language from user profile on mount
    useEffect(() => {
        const initializeLanguage = async () => {
            let initialLanguage: Language = 'de';
            
            // Priority 1: Check if user data has language setting (ONLY source of truth!)
            const userData = getUserDataCache();
            if (userData?.language && String(userData.language).trim()) {
                initialLanguage = String(userData.language).trim() as Language;
                console.log('🌍 Using language from user profile (sessionStorage cache):', initialLanguage);
                await loadAndSetLanguage(initialLanguage);
                return;
            }
            
            // Priority 2: Detect browser language (fallback only if no user data)
            const browserLang = navigator.language.split('-')[0] as Language;
            try {
                const codes = await fetchAvailableLanguageCodes();
                const codeSet = new Set(codes.map((c) => c.code));
                if (codeSet.has(browserLang)) {
                    initialLanguage = browserLang;
                    console.log('🌍 Using browser language as fallback:', initialLanguage);
                } else {
                    console.log('🌍 Using default language:', initialLanguage);
                }
            } catch {
                console.log('🌍 Using default language:', initialLanguage);
            }
            
            await loadAndSetLanguage(initialLanguage);
        };

        initializeLanguage();
        
        // Listen for user data updates to sync language
        const handleUserUpdate = () => {
            const userData = getUserDataCache();
            if (userData?.language && String(userData.language).trim()) {
                const userLanguage = String(userData.language).trim() as Language;
                if (userLanguage !== currentLanguage) {
                    console.log('🔄 Syncing language with user data (sessionStorage cache):', userLanguage);
                    loadAndSetLanguage(userLanguage);
                }
            }
        };

        // Listen for user info update events
        window.addEventListener('userInfoUpdated', handleUserUpdate);
        
        return () => {
            window.removeEventListener('userInfoUpdated', handleUserUpdate);
        };
    }, []);

    const setLanguage = async (language: Language) => {
        // Load the new language immediately for UI
        await loadAndSetLanguage(language);
        
        // IMPORTANT: This should ONLY be called after the backend profile is updated
        // The settings component should:
        // 1. Update backend user profile with new language
        // 2. Refetch user data (which includes the new language)
        // 3. Update sessionStorage cache with new data (via setUserDataCache)
        // 4. Call this function to sync the UI
    };

    const reloadLanguage = async () => {
        await loadAndSetLanguage(currentLanguage);
    };

    const refreshAvailableLanguages = useCallback(async () => {
        try {
            const list = await fetchAvailableLanguageCodes();
            setAvailableLanguages(list);
        } catch (e) {
            console.error('Failed to load language codes:', e);
        }
    }, []);

    useEffect(() => {
        refreshAvailableLanguages();
    }, [refreshAvailableLanguages]);

    const _applyParams = (template: string, params?: TranslateParams): string => {
        if (!params) return template;
        let out = template;
        for (const [paramKey, rawVal] of Object.entries(params)) {
            if (rawVal === undefined || rawVal === null) continue;
            out = out.split(`{${paramKey}}`).join(String(rawVal));
        }
        return out;
    };

    const t = (key: string, paramsOrFallback?: TranslateParams | string): string => {
        let params: TranslateParams | undefined;
        if (typeof paramsOrFallback === 'string') {
            params = undefined;
        } else {
            params = paramsOrFallback;
        }

        const resolved =
            translations[key] ??
            deTranslations[key] ??
            (typeof paramsOrFallback === 'string' ? paramsOrFallback : undefined) ??
            `[${key}]`;
        return _applyParams(resolved, params);
    };

    const contextValue: LanguageContextType = {
        currentLanguage,
        setLanguage,
        t,
        isLoading,
        reloadLanguage,
        availableLanguages,
        refreshAvailableLanguages,
    };

    return (
        <LanguageContext.Provider value={contextValue}>
            {children}
        </LanguageContext.Provider>
    );
};

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