import { j as IStorage } from './storage.interface-2HKvqdAJ.js';

/**
 * Тип для функции отписки от событий
 */
type Unsubscribe = VoidFunction;
/**
 * Опции для выполнения запроса
 */
interface QueryOptions {
    /** Отключить кэширование для этого запроса */
    disableCache?: boolean;
    /** Signal для отмены запроса */
    signal?: AbortSignal;
    /** Таймаут в миллисекундах (переопределяет глобальный) */
    timeout?: number;
    /** Дополнительные заголовки */
    headers?: Headers;
    /** Пользовательский контекст */
    context?: Record<string, any>;
    /** Ключи заголовков, влияющие на кэш (для конкретного запроса) */
    cacheableHeaderKeys?: string[];
    /** Формат ответа (переопределяет формат из RequestDefinition) */
    responseFormat?: ResponseFormat;
    /** Название файла при скачивании (переопределяет fileName из RequestDefinition) */
    fileName?: string;
    /** Тип файла при скачивании (переопределяет fileType из RequestDefinition) */
    fileType?: string;
    /** Автоматически скачать файл после получения */
    downloadFile?: boolean;
    /**
     * Функция для повторного выполнения запроса
     */
    retry?: <T = any, R = any>(params: T, options?: QueryOptions) => Promise<R>;
}
/**
 * Метаданные для файла
 */
interface FileMetadata {
    /** Имя файла */
    fileName: string;
    /** Тип файла (MIME-тип) */
    fileType: string;
    /** Размер файла в байтах */
    size?: number;
    /** Дата создания файла */
    createdAt?: Date | string;
    /** Дата изменения файла */
    updatedAt?: Date | string;
}
/**
 * Результат скачивания файла
 */
interface FileDownloadResult<T = Blob | ArrayBuffer> {
    /** Данные файла */
    data: T;
    /** Метаданные файла */
    metadata: FileMetadata;
    /** HTTP-статус */
    status: number;
    /** Текст статуса */
    statusText: string;
    /** Заголовки ответа */
    headers: Headers;
    /** Успешна ли загрузка */
    ok: boolean;
}
/**
 * Результат выполнения запроса
 */
interface QueryResult<T = any, E = Error> {
    /** Данные ответа (при успешном запросе) */
    data?: T;
    /** Ошибка (при неуспешном запросе) */
    error?: E;
    /** Флаг успешности запроса */
    ok: boolean;
    /** HTTP-статус */
    status: number;
    /** Текстовое описание статуса */
    statusText: string;
    /** Заголовки ответа */
    headers: Headers;
    /** Результат скачивания файла (если responseFormat - Blob или ArrayBuffer) */
    fileDownloadResult?: FileDownloadResult;
    fromCache?: boolean;
}

/**
 * Конфигурация эндпоинта
 */
interface EndpointConfig<RequestParams extends Record<string, any> = any, RequestResult = any> {
    /** Функция для создания определения запроса из параметров */
    request: (params: RequestParams, context?: Record<string, any>) => RequestDefinition<RequestParams>;
    /** Настройки кэша для эндпоинта */
    cache?: CacheConfig;
    /** Теги эндпоинта для группировки в кэше */
    tags?: string[];
    /** Теги, которые инвалидируются при успешном запросе */
    invalidatesTags?: string[];
    /** Функция для подготовки заголовков (дополняет глобальную) */
    prepareHeaders?: (headers: Headers, context: ApiContext<RequestParams>) => Promise<Headers>;
    /** Добавить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */
    includeCacheableHeaderKeys?: string[];
    /** Исключить ключи заголовков, влияющие на кэш (Дополняет глобавльные ключи) */
    excludeCacheableHeaderKeys?: string[];
}
/**
 * Состояние эндпоинта
 * Содержит информацию о текущем состоянии запроса и данные
 */
interface EndpointState {
    /** Статус запроса */
    status: 'idle' | 'loading' | 'success' | 'error';
    /** Ошибка (при неуспешном запросе) */
    error?: Error;
    /** Количество вызовов */
    fetchCounts: number;
    /** Метаданные эндпоинта */
    meta: Endpoint['meta'];
    /** Какие заголовки участвовали в формировании ключа кэша (итоговые) */
    cacheableHeaders: string[];
}
/**
 * Состояние самого запроса
 */
interface RequestState<ResponseData = any, RequestParams extends Record<string, any> = any, E = Error> {
    status: 'loading' | 'success' | 'error' | 'idle';
    data?: ResponseData;
    error?: E;
    headers: Record<string, any> | Headers;
    requestParams: RequestParams;
    fromCache: boolean;
}
interface SubscribeOptions {
    /** Автоматически отписаться после завершения запроса */
    autoUnsubscribe?: boolean;
}
/**
 * Дополнительные методы для request
 */
interface RequestResponseModify<T, P extends Record<string, any> = any> {
    id: string;
    /**
     * Подписка на изменения состояния запроса
     */
    subscribe: (listener: (state: RequestState<T, P>) => void, options?: SubscribeOptions) => VoidFunction;
    /**
     * Ожидание завершения запроса
     * @returns Promise с результатом запроса
     */
    wait: () => Promise<QueryResult<T, Error>>;
    waitWithCallbacks: (handlers: {
        idle?: (request: RequestState<T, P>) => void;
        loading?: (request: RequestState<T, P>) => void;
        success?: (data: T | undefined, request: RequestState<T, P>) => void;
        error?: (error: Error | undefined, request: RequestState<T, P>) => void;
    }) => Promise<QueryResult<T, Error>>;
    /**
     * Отменить запрос
     */
    abort: VoidFunction;
    then<TResult1 = QueryResult<T, Error>, TResult2 = never>(onfulfilled?: ((value: QueryResult<T, Error>) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: Error) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
    catch<TResult = never>(onrejected?: ((reason: Error) => TResult | PromiseLike<TResult>) | undefined | null): Promise<QueryResult<T, Error> | TResult>;
    finally(onfinally?: VoidFunction | undefined | null): Promise<QueryResult<T, Error>>;
}
/**
 * Структура эндпоинта
 *
 * Эндпоинт - это всего лишь определение того6 как будет вызван метод
 * Эндпоинт может быть вызван в разных частях приложения с разными параметрами
 * По этому нет смысла хранить ответы так как они будут перезаписываться
 * метод subscribe больше нужен для мониторинга
 * meta - метаинформация по эндпоинту (то как он сконфигурирован)
 */
interface Endpoint<RequestParams extends Record<string, any> = any, ResponseData = any> {
    /** Счетчик вызова конкретного эндпоинта в проекте */
    fetchCounts: number;
    /** Выполнить запрос с параметрами */
    request: (params: RequestParams, options?: QueryOptions) => RequestResponseModify<ResponseData>;
    /** Подписаться на изменения состояния эндпоинта (в основном для сбора статистики) */
    subscribe: (callback: (state: EndpointState) => void) => Unsubscribe;
    /** Сбросить состояние */
    reset: () => Promise<void>;
    /** Метаданные эндпоинта */
    meta: {
        /** Имя эндпоинта */
        name: string;
        /** Теги эндпоинта */
        tags: string[];
        /** Теги, которые инвалидируются */
        invalidatesTags: string[];
        /** Настройки кэша */
        cache: CacheConfig;
    };
    destroy: VoidFunction;
}
/**
 * Функция для создания типизированных эндпоинтов
 */
type CreateEndpoint = <RequestParams extends Record<string, any>, RequestResult>(config: EndpointConfig<RequestParams, RequestResult>) => EndpointConfig<RequestParams, RequestResult>;

/**
 * Форматы ответа от сервера
 */
declare enum ResponseFormat {
    /** JSON-объект (по умолчанию) */
    Json = "json",
    /** Blob-объект для файлов */
    Blob = "blob",
    /** ArrayBuffer для бинарных данных */
    ArrayBuffer = "arrayBuffer",
    /** Текстовый формат */
    Text = "text",
    /** FormData для форм */
    FormData = "formData",
    /** Без преобразования - возвращает сырой ответ */
    Raw = "raw"
}
/**
 * Настройки кэша
 * Может быть объектом с параметрами или boolean (true для кэширования с настройками по умолчанию, false для отключения)
 */
type CacheConfig = boolean | {
    /** Время жизни кэша в миллисекундах */
    ttl?: number;
    /** Настройки периодической очистки */
    cleanup?: {
        /** Включить периодическую очистку */
        enabled: boolean;
        /** Интервал очистки в миллисекундах */
        interval?: number;
    };
    /** Инвалидировать кэш при ошибке */
    invalidateOnError?: boolean;
};
/**
 * Определение запроса
 * Содержит всю необходимую информацию для выполнения HTTP-запроса
 */
interface RequestDefinition<RequestParams extends Record<string, any>> {
    /** Путь запроса (относительный или абсолютный URL) */
    path: string;
    /** HTTP-метод */
    method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
    /** Тело запроса (автоматически сериализуется) */
    body?: any;
    /** Параметры запроса (автоматически добавляются в URL) */
    query?: RequestParams;
    /** HTTP-заголовки */
    headers?: Record<string, string>;
    /** Формат ответа (по умолчанию json) */
    responseFormat?: ResponseFormat;
    /** Имя файла для автоматического скачивания */
    fileName?: string;
    /** Тип контента для автоматического скачивания */
    fileType?: string;
}
/**
 * Контекст API для использования в prepareHeaders и других функциях
 * Содержит вспомогательные методы и информацию о запросе
 */
interface ApiContext<RequestParams extends Record<string, any> = any> {
    /** Параметры запроса */
    requestParams?: RequestParams;
    /** Получить значение из localStorage */
    getFromStorage: <T>(key: string) => T | undefined;
    /** Получить значение cookie */
    getCookie: (name: string) => string | undefined;
    /** Поддержка для дополнительных свойств */
    [key: string]: any;
}
/**
 * Аргументы для создания fetch-запроса
 */
interface FetchBaseQueryArgs {
    /** Базовый URL для всех запросов */
    baseUrl: string;
    /** Функция для подготовки заголовков, может быть асинхронной */
    prepareHeaders?: (headers: Headers, context: ApiContext) => Promise<Headers>;
    /** Таймаут запроса в миллисекундах */
    timeout?: number;
    /** Пользовательская fetch-функция */
    fetchFn?: typeof fetch;
    credentials?: RequestCredentials;
}
interface CreateApiClientOptions<T extends Record<string, EndpointConfig<any, any>> = Record<string, EndpointConfig<any, any>>> {
    storage: IStorage;
    /** Настройки кэша
     * если явно указан false - значит ни один запрос НЕ будет кэшироваться, даже если в эндпоинтах указаны параметры
     * */
    cache?: CacheConfig;
    /** Базовый запрос или его настройки */
    baseQuery: FetchBaseQueryArgs;
    /** Функция для создания эндпоинтов */
    endpoints?: (create: CreateEndpoint) => Promise<T>;
    /** Глобальные заголовки, влияющие на кэш */
    cacheableHeaderKeys?: string[];
}
/**
 * Извлечение типа параметров из конфигурации эндпоинта
 */
type ExtractParamsType<T> = T extends EndpointConfig<infer P, any> ? P : never;
/**
 * Извлечение типа результата из конфигурации эндпоинта
 */
type ExtractResultType<T> = T extends EndpointConfig<any, infer R> ? R : never;

type EndpointsResult<F> = F extends (create: any) => Promise<infer R> ? R : never;
declare class ApiClient<EndpointsFn extends (create: CreateEndpoint) => Promise<Record<string, EndpointConfig<any, any>>>> {
    /** Хранилище запросов */
    private queryStorage;
    private readonly cacheableHeaderKeys;
    private readonly globalCacheConfig;
    private readonly baseQueryConfig;
    private readonly storageExternal;
    private readonly createEndpoints;
    /** Реестр эндпоинтов */
    private endpoints;
    constructor(options: Omit<CreateApiClientOptions, 'endpoints'> & {
        endpoints: EndpointsFn;
    });
    init(): Promise<this>;
    private initializeEndpoints;
    /**
     * Получает все эндпоинты с улучшенной типизацией
     * @returns Типизированный объект эндпоинтов
     */
    getEndpoints(): {
        [K in keyof EndpointsResult<EndpointsFn>]: Endpoint<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>;
    };
    /**
     * Выполняет запрос к API с типизацией и обработкой ошибок
     * @param endpointName Имя эндпоинта (с подсказками TypeScript)
     * @param params Параметры запроса (с типизацией)
     * @param options Опции запроса
     * @returns Promise с типизированным результатом запроса
     */
    request<K extends keyof EndpointsResult<EndpointsFn> & string>(endpointName: K, params: ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, options?: QueryOptions): Promise<QueryResult<ExtractResultType<EndpointsResult<EndpointsFn>[K]>, Error>>;
    destroy(): Promise<void>;
}

/**
 * Логгер для API
 */
declare const apiLogger: {
    debug: (message: string, ...args: any[]) => void;
    log: (message: string, ...args: any[]) => void;
    info: (message: string, ...args: any[]) => void;
    warn: (message: string, ...args: any[]) => void;
    error: (message: string, ...args: any[]) => void;
};
/**
 * Создает уникальный идентификатор
 * @returns Строка с уникальным идентификатором
 */
declare function createUniqueId(name?: string): string;
/**
 * Преобразует объект Headers в обычный объект
 * @param headers Объект Headers
 * @returns Обычный объект с заголовками
 */
declare function headersToObject(headers: Headers): Record<string, string>;

export { ApiClient, ResponseFormat, apiLogger, createUniqueId, headersToObject };
