import { FormattableString } from 'gramio';

type Values<T> = T[keyof T];
type SafeGet<T, K extends string> = T extends Record<K, unknown> ? T[K] : never;
type LocaleValue = string | FormattableString;
type LocaleArgs<Arguments extends any[] = any[]> = (...args: Arguments) => LocaleValue;
type LocaleItem<Arguments extends any[] = any[]> = LocaleArgs<Arguments> | LocaleValue;
interface LanguageMap {
    [key: string]: LocaleItem | LanguageMap;
}
type NestedKeysDelimited<T> = Values<{
    [key in Extract<keyof T, string>]: T[key] extends LocaleItem ? key : `${key}.${T[key] extends infer R ? NestedKeysDelimited<R> : never}`;
}>;
type GetValueNested<T, K extends string> = K extends `${infer P}.${infer Q}` ? GetValueNested<SafeGet<T, P>, Q> : SafeGet<T, K>;
type LanguagesMap = Record<string, LanguageMap>;
type ExtractArgsParams<Item extends LocaleItem> = Item extends LocaleArgs<infer Args> ? Args : [];
type ExtractItemValue<Item extends LocaleItem, FallbackItem extends LocaleItem = never> = [Item] extends [never] ? [FallbackItem] extends [never] ? never : ExtractItemValue<FallbackItem> : Item extends LocaleArgs ? ReturnType<Item> : Item;
type ShouldFollowLanguage<Language extends LanguageMap> = {
    [Key in keyof Language]?: Language[Key];
};
type ShouldFollowLanguageStrict<Language extends LanguageMap> = {
    [Key in keyof Language]: Language[Key];
};
type SoftString<Strings> = Strings | ({} & string);
interface I18nOptions<Languages extends LanguagesMap, PrimaryLanguage extends keyof Languages> {
    languages: Languages;
    primaryLanguage: PrimaryLanguage;
}
type ExtractLanguages<T> = T extends {
    _: {
        languages: infer Languages;
    };
} ? Languages : never;
type GetI18nParams<I18n extends I18nOptions<any, any>, Key extends NestedKeysDelimited<ExtractLanguages<I18n>>[I18n["primaryLanguage"]]> = Key extends NestedKeysDelimited<ExtractLanguages<I18n>>[I18n["primaryLanguage"]] ? ExtractArgsParams<GetValueNested<ExtractLanguages<I18n>[I18n["primaryLanguage"]], Key>> : never;
type GetI18nKeys<I18n extends I18nOptions<any, any>> = NestedKeysDelimited<ExtractLanguages<I18n>[I18n["primaryLanguage"]]>;

declare function pluralizeEnglish<T>(n: number, one: T, many: T): T;

declare function pluralizeRussian<T>(count: number, one: T, few: T, many: T): T;

declare function defineI18n<Languages extends LanguagesMap, PrimaryLanguage extends keyof Languages>({ languages, primaryLanguage }: I18nOptions<Languages, PrimaryLanguage>): {
    t: <Language extends SoftString<keyof Languages>, Key extends Language extends keyof Languages ? NestedKeysDelimited<Languages[Language]> : NestedKeysDelimited<Languages[PrimaryLanguage]>, Item extends Language extends keyof Languages ? GetValueNested<Languages[Language], Key> : GetValueNested<Languages[PrimaryLanguage], Key>, FallbackItem extends GetValueNested<Languages[PrimaryLanguage], Key>>(language: Language, key: Key, ...args: [Item] extends [never] ? ExtractArgsParams<FallbackItem_1> : ExtractArgsParams<Item_1>) => ExtractItemValue<Item, FallbackItem>;
    languages: (keyof Languages)[];
    primaryLanguage: PrimaryLanguage;
    buildT: <Language extends SoftString<keyof Languages> = PrimaryLanguage>(language?: Language) => <Key extends Language extends keyof Languages ? NestedKeysDelimited<Languages[Language]> : NestedKeysDelimited<Languages[PrimaryLanguage]>, Item extends Language extends keyof Languages ? GetValueNested<Languages[Language], Key> : GetValueNested<Languages[PrimaryLanguage], Key>, FallbackItem extends GetValueNested<Languages[PrimaryLanguage], Key>>(key: Key, ...args: Item extends unknown ? ExtractArgsParams<FallbackItem> : ExtractArgsParams<Item>) => ExtractItemValue<Item, FallbackItem>;
    _: {
        languages: Languages;
        primaryLanguage: PrimaryLanguage;
    };
};

export { type ExtractArgsParams, type ExtractItemValue, type ExtractLanguages, type GetI18nKeys, type GetI18nParams, type GetValueNested, type I18nOptions, type LanguageMap, type LanguagesMap, type LocaleArgs, type LocaleItem, type LocaleValue, type NestedKeysDelimited, type ShouldFollowLanguage, type ShouldFollowLanguageStrict, type SoftString, defineI18n, pluralizeEnglish, pluralizeRussian };
