import { create } from 'zustand';

import { LangsBDEFHIJPRZEnum } from '@/api/types';

import {
    local,
    type LocalItemType,
} from './local';

const SUPPORTED_LANGS: LangsBDEFHIJPRZEnum[] = [
    'ru', 'en', 'de', 'fr', 'it', 'es', 'pt', 'hi', 'bn', 'id', 'zh', 'ja',
];

const isValidLang = (lang: string | null): lang is LangsBDEFHIJPRZEnum =>
    !!lang && SUPPORTED_LANGS.includes(lang as LangsBDEFHIJPRZEnum);

const resolveInitialLang = (): LangsBDEFHIJPRZEnum => {
    const storedLang = localStorage.getItem('lang');
    if (isValidLang(storedLang)) {
        return storedLang;
    }

    const browserLang = navigator.language.split('-')[0];
    if (isValidLang(browserLang)) {
        return browserLang;
    }

    return 'en';
};

interface LangStoreState {
    lang: LangsBDEFHIJPRZEnum;
    availableLangs: LangsBDEFHIJPRZEnum[];
    langsResolved: boolean;
}

export const useLangStore = create<LangStoreState>(() => {
    const lang = resolveInitialLang();
    if (typeof document !== 'undefined') {
        document.documentElement.lang = lang;
    }
    return {
        lang,
        availableLangs: SUPPORTED_LANGS,
        langsResolved: false,
    };
});

export const useLang = () => useLangStore((state) => state.lang);

export const useCanChangeLang = () => useLangStore((state) => state.availableLangs.length > 1);

export const useAvailableLangs = () => useLangStore((state) => state.availableLangs);

export class Lang {

    public static initLang() {
        this.setCurrentLang(resolveInitialLang());
    }

    private static pendingKeys = new Set<string>();

    public static getCurrentLang() {
        return useLangStore.getState().lang;
    }

    public static canChangeLang() {
        return useLangStore.getState().availableLangs.length > 1;
    }

    public static applyServerLangs(langs?: LangsBDEFHIJPRZEnum[]) {
        const filtered = langs?.length ? langs.filter(isValidLang) : [];
        const effectiveLangs = filtered.length ? filtered : ['ru' as LangsBDEFHIJPRZEnum];

        useLangStore.setState({
            availableLangs: effectiveLangs,
            langsResolved: true,
        });

        if (effectiveLangs.length === 1) {
            this.setCurrentLang(effectiveLangs[0]);
            return;
        }

        const currentLang = this.getCurrentLang();
        if (!effectiveLangs.includes(currentLang)) {
            this.setCurrentLang(effectiveLangs[0]);
        }
    }

    public static manualChangeLang(lang: LangsBDEFHIJPRZEnum) {
        if (!this.canChangeLang()) {
            return;
        }
        this.setCurrentLang(lang);
    }

    public static setCurrentLang(lang: LangsBDEFHIJPRZEnum) {
        localStorage.setItem('lang', lang);
        useLangStore.setState({ lang });
        document.documentElement.lang = lang;
    }

    private static async addKeyToLocal(key: string) {
        // Предотвращаем множественные запросы для одного ключа
        if (this.pendingKeys.has(key)) {
            return;
        }
        this.pendingKeys.add(key);

        // В dev режиме отправляем запрос на сервер для добавления ключа
        if (import.meta.env.DEV) {
            try {
                await fetch('/api/add-lang-key', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ key }),
                });
            } catch (error) {
                console.warn(`Не удалось добавить ключ "${key}" в local.ts:`, error);
            } finally {
                this.pendingKeys.delete(key);
            }
        }
    }

    public static key(key: string) {

        let value: LocalItemType = local?.[key];

        if (!value) {
            // В dev режиме пытаемся добавить ключ в local.ts
            if (import.meta.env.DEV) {
                this.addKeyToLocal(key);
            }
            return key;
        }

        return value[this.getCurrentLang()];


    }


}

export { LL } from './LL';
export { LLRender, resolveLLText } from './llUtils';
export { useLLText } from './localizationService';