import { router, usePage } from '@inertiajs/react';
import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo } from 'react';
import { setActiveLocale } from '@/lib/format';
import { setActiveTranslator } from '@/lib/time';

interface Language {
    code: string;
    country_code?: string | null;
    name: string;
    native_name: string;
    is_rtl: boolean;
    is_default?: boolean;
}

interface LocaleData {
    current: string;
    isRtl: boolean;
    available: Language[];
}

interface LanguageContextType {
    locale: string;
    isRtl: boolean;
    availableLanguages: Language[];
    setLocale: (locale: string) => void;
    t: (key: string, replacements?: Record<string, string | number>) => string;
}

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

const STORAGE_KEY = 'arcade-locale';
const RTL_STORAGE_KEY = 'arcade-locale-rtl';

/**
 * Resolve a translation key against a flat translations map.
 * Supports `:placeholder` replacements and pipe-based plural forms
 * (`singular|plural`, picked via a `count` replacement).
 */
export function translate(
    translations: Record<string, string> | undefined,
    key: string,
    replacements?: Record<string, string | number>,
): string {
    let translation = translations?.[key] ?? key;

    if (translation.includes('|') && replacements && 'count' in replacements) {
        const forms = translation.split('|');
        const count = Number(replacements.count);
        translation = count === 1 ? forms[0] : forms[forms.length - 1];
    }

    if (replacements) {
        Object.entries(replacements).forEach(([k, v]) => {
            translation = translation.replace(`:${k}`, String(v));
        });
    }

    return translation;
}

interface LanguageProviderProps {
    children: ReactNode;
}

export function LanguageProvider({ children }: LanguageProviderProps) {
    const props = usePage().props as {
        locale?: LocaleData;
        translations?: Record<string, string>;
    };

    const locale = props.locale?.current ?? 'en';
    const isRtl = props.locale?.isRtl ?? false;
    const availableLanguages = useMemo(() => props.locale?.available ?? [], [props.locale?.available]);
    const translations = useMemo(() => props.translations ?? {}, [props.translations]);

    useEffect(() => {
        document.documentElement.dir = isRtl ? 'rtl' : 'ltr';
        document.documentElement.lang = locale;
        setActiveLocale(locale);
        try {
            localStorage.setItem(STORAGE_KEY, locale);
            localStorage.setItem(RTL_STORAGE_KEY, String(isRtl));
        } catch {
            // ignore — private mode or quota exceeded
        }
    }, [isRtl, locale]);

    const setLocale = useCallback(
        (newLocale: string) => {
            const newLanguage = availableLanguages.find((l) => l.code === newLocale);
            try {
                localStorage.setItem(STORAGE_KEY, newLocale);
                localStorage.setItem(RTL_STORAGE_KEY, String(newLanguage?.is_rtl ?? false));
            } catch {
                // ignore
            }

            router.post(
                '/locale',
                { locale: newLocale },
                { preserveState: false, preserveScroll: true },
            );
        },
        [availableLanguages],
    );

    const t = useMemo(
        () =>
            (key: string, replacements?: Record<string, string | number>) =>
                translate(translations, key, replacements),
        [translations],
    );

    // Keep singletons current on every render (cheap; idempotent module-state writes).
    setActiveLocale(locale);
    setActiveTranslator(t);

    useEffect(() => {
        setActiveTranslator(t);
    }, [t]);

    const value = useMemo(
        () => ({ locale, isRtl, availableLanguages, setLocale, t }),
        [locale, isRtl, availableLanguages, setLocale, t],
    );

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

export function useLanguage(): LanguageContextType {
    const ctx = useContext(LanguageContext);
    if (ctx === undefined) {
        throw new Error('useLanguage must be used within a LanguageProvider');
    }

    return ctx;
}

export function useTranslation() {
    const { t, locale, isRtl } = useLanguage();

    return { t, locale, isRtl };
}
