import { IAppConfig, IAppParam, TAppType, TAppMode } from './interfaces/IAppContext';
import { TBotContent, TBotResponseCb, TCommandGroupMode, TPlugin } from './interfaces/IBot';
import { ICommandParam, TSlots, TCommandResolver, IStepParam } from './utils/CommandReg';
import { IncomingMessage, ServerResponse, Server } from 'node:http';
import { BotController, IUserData } from '../controller';
import { AppContext } from './AppContext';
import { ILogger } from './interfaces/ILogger';
/**
 * Тип для класса контроллера приложения
 */
export type TBotControllerClass<T extends IUserData = IUserData> = new (appContext: AppContext) => BotController<T>;
/**
 * Результат выполнения запроса от платформы - ответ, который будет отправлен пользователю
 * Может быть ответом для Алисы, Маруси или текстовым сообщением
 *
 * @example
 * ```ts
 * // Ответ для Алисы
 * const alisaResponse: TRunResult = {
 *   response: {
 *     text: 'Привет!',
 *     end_session: false
 *   },
 *   version: '1.0'
 * };
 *
 * // Ответ для Маруси
 * const marusiaResponse: TRunResult = {
 *   response: {
 *     text: 'Привет!',
 *     end_session: false
 *   },
 *   version: '1.0'
 * };
 *
 * // Простой текстовый ответ
 * const textResponse: TRunResult = 'Привет!';
 * ```
 */
export type TRunResult = object | string;
export * from './interfaces/IBot';
/**
 * Функция для обработки следующего шага в цепочке промежуточных функций
 */
export type MiddlewareNext = () => Promise<void>;
/**
 * Функция промежуточной обработки
 */
export type MiddlewareFn = (ctx: BotController, next: MiddlewareNext) => void | Promise<void>;
/**
 * Тип для кастомного обработчика определения платформы.
 *
 * Позволяет разработчику взять на себя определение типа платформы для входящего запроса.
 * Обработчик выполняется **до** встроенного автоопределения через адаптеры.
 *
 * @param query - Тело запроса (обычно объект, может быть строкой, если запрос не распарсен).
 * @param headers - HTTP-заголовки запроса (если доступны).
 * @param detect - Функция, вызывающая стандартный механизм определения платформы
 *                 (перебор зарегистрированных адаптеров). Принимает те же параметры,
 *                 что и резолвер, и возвращает имя платформы или `null`.
 * @returns Имя платформы (строка) или `null`, если платформа не определена.
 *
 * @example
 * ```ts
 * bot.setPlatformResolver((query, headers, detect) => {
 *   // Сначала пробуем стандартное определение
 *   const platform = detect(query, headers);
 *   if (platform === 'telegram' && headers?.['x-force-vk']) {
 *     return 'vk';
 *   }
 *   return platform;
 * });
 * ```
 */
export type TPlatformResolver = (query: unknown, headers?: Record<string, unknown>, detect?: (uBody: unknown, headers?: Record<string, unknown>) => TAppType | null) => TAppType | null;
/**
 * Мультиплатформенный фреймворк для разработки голосовых навыков и чат-ботов. Он даёт единую бизнес-логику для все платформ — но одинаково эффективен, даже если вы работаете только с одной.
 *
 * **`Bot` — главный класс**, управляющий всем жизненным циклом приложения:
 *  - регистрацией платформ (Алиса, Telegram, VK, Маруся, Max и др.);
 *  - обработкой входящих запросов;
 *  - маршрутизацией команд;
 *  - middleware;
 *  - работой с базой данных;
 *  - логированием
 *  - метриками.
 *
 * Фреймворк построен на **адаптерах** — каждый адаптер отвечает за преобразование
 * специфичного для платформы запроса в унифицированный `BotController`, который
 * содержит всю информацию о пользователе, текст команды, NLU, состояние и методы ответа
 * (кнопки, карточки, TTS). Вы пишете **один код**, а фреймворк доставляет его
 * на все поддерживаемые платформы.
 *
 * ## 📖 КРАТКОЕ РУКОВОДСТВО
 *
 * 1. **Создайте приложение:** `const bot = new Bot();`
 * 2. **Настройте токены:** `bot.setAppConfig({ tokens: { telegram: {token: '...'}} });`
 * 3. **Добавьте логику при необходимости:** `bot.initBotController(MyController);`
 * 4. **Добавьте команды:** `bot.addCommand('start', ['старт'], handler);`
 * 5. **Запустите:** `bot.start();`
 *
 * ## 🎯 Ключевые возможности
 *  * - ✅ **Поддержка множества платформ** через подключаемые адаптеры (Алиса, Telegram, VK, Маруся и др.)
 *  * - ✅ **Единая логика** для голосовых навыков и ботов
 *  * - ✅ **Мощная система команд и интентов** с поддержкой регулярных выражений
 *  * - ✅ **Управление состоянием диалога** (шаги) и пользовательскими данными
 *  * - ✅ **Встроенная работа с БД** (MongoDB через плагины)
 *  * - ✅ **Middleware и плагины** для расширения функциональности
 *  * - ✅ **Гибкая настройка** (режимы разработки/продакшена, защита от ReDoS, кастомные резолверы команд)
 *  * - ✅ **Логирование и метрики** для отладки и мониторинга
 *
 * ## 🚀 БЫСТРЫЙ СТАРТ
 * Создание простого Telegram бота
 * ```ts
 * import { Bot } from 'umbot';
 * import { botPlatforms } from 'umbot/plugins';
 *
 * // 1. Создаем бота для Telegram
 * const bot = new Bot();
 *
 * // 2. Настраиваем токен (рекомендуется через .env файл)
 * bot.setAppConfig({
 *   env: 'local'
 * });
 *
 * // 3. Говорим приложению, что нужно поддерживать только платформы для чат-ботов
 * bot.use(botPlatforms);
 *
 * // 4. Добавляем команды
 * bot.addCommand('help', ['помощь', 'справка'], (cmd, controller) => {
 *   controller.text = 'Я могу:\n• Приветствовать\n• Помогать\n• И многое другое!';
 * });
 *
 * // 5. Запускаем сервер
 * bot.start('localhost', 3000);
 *
 * // 6. Настройте webhook в Telegram: https://api.telegram.org/bot{YOUR_TOKEN}/setWebhook?url=https://ваш-домен/webhook
 * ```
 *
 * Создание простого приложения со своим контроллером:
 * ```ts
 * const bot = new Bot();
 * bot.setPlatformParams({
 *   intents: [{
 *     name: 'greeting',
 *     slots: ['привет', 'здравствуй']
 *   }]
 * });
 *
 * class MyController extends BotController {
 *   public action(intentName: string | null): void {
 *     if (intentName === 'greeting') {
 *       this.text = 'Привет! Я ваш помощник 🤖';
 *       this.buttons
 *         .addBtn('Помощь')
 *         .addBtn('Настройки');
 *     }
 *   }
 * }
 *
 * bot.initBotController(MyController);
 * ```
 * Использование с базой данных:
 * ```ts
 * import { Bot } from 'umbot'
 * import { MongoAdapter } from 'umbot/plugins'
 * const bot = new Bot();
 * bot.use(new MongoAdapter({
 *     host: 'localhost',
 *     database: 'bot_db',
 *     user: 'user',
 *     pass: 'password'
 *   }));
 * ```
 *
 * @template TUserData Тип пользовательских данных, по умолчанию {@link IUserData}
 * @see BotController
 */
export declare class Bot<TUserData extends IUserData = IUserData> {
    #private;
    /**
     * Полученный запрос от пользователя.
     * Может быть JSON-строкой, текстом или null
     */
    protected _content: TBotContent;
    /**
     * Создает новый экземпляр приложения
     *
     * @param {TAppType} [type] - Тип платформы (по умолчанию автоопределение)
     * @param {TBotControllerClass} [botController] - Контроллер с логикой
     *
     * @throws {Error} Если не удалось инициализировать тип платформы
     *
     * @example
     * ```ts
     * // Создание навыка для Алисы
     * const bot = new Bot(T_ALISA, MyController);
     *
     * // Создание бота для Telegram
     * const bot = new Bot(T_TELEGRAM, MyController);
     *
     * // Создание бота для VK
     * const bot = new Bot(T_VK, MyController);
     *
     * // Создание приложения по умолчанию
     * const bot = new Bot();
     * ```
     */
    constructor(type?: TAppType, botController?: TBotControllerClass<TUserData>);
    /**
     * Явно устанавливает тип платформы для всего приложения. Стоит использовать в крайнем случае
     * @param appType
     */
    set appType(appType: TAppType | 'auto');
    /**
     * Возвращает установленный тип приложения.
     */
    get appType(): string;
    /**
     * Задает режим работы с регулярным выражениями.
     * При значении auto, регулярные выражения будут группироваться в группу, благодаря чему уменьшается время обработки. Логика начинает отрабатывать после того, как добавили более 300 команд.
     * При значении no-group, группировка регулярных выражений производиться не будет, из-за чего каждое регулярное выражение будет обрабатываться отдельно. Указывать данное значение стоит в том случае, если вы получаете сильную деградацию при обработке групп.
     * При значении group, все регулярные выражения будут добавляться в группу. Перед использованием данного значения, перепроверьте производительность, так как при группировке определенных регулярных выражений, производительность может быть ниже.
     * @param mode - Определяет режим работы с регулярными выражениями.
     */
    setCommandGroupMode(mode: TCommandGroupMode): this;
    /**
     * Устанавливает кастомный обработчик для определения типа платформы.
     *
     * По умолчанию фреймворк определяет платформу автоматически, перебирая зарегистрированные адаптеры
     * и вызывая их метод `isPlatformOnQuery`. Этот метод позволяет переопределить логику определения,
     * что полезно в следующих случаях:
     * - Нужно добавить поддержку кастомной платформы, не создавая адаптер.
     * - Требуется изменить стандартное поведение для конкретного набора запросов
     *   (например, по заголовкам или по содержимому запроса).
     * - Необходимо выполнить какую-то логику до того, как запрос попадёт в адаптер.
     *
     * **Важно:** резолвер выполняется **до** вызова `isPlatformOnQuery` любого адаптера.
     * Если резолвер возвращает строку (имя платформы), фреймворк использует это значение
     * и не выполняет стандартное автоопределение. Если возвращает `null`, то запускается
     * стандартный перебор адаптеров.
     *
     * В резолвер передаётся опциональная функция `detect`, которая вызывает встроенное
     * автоопределение. Это позволяет, например, получить результат стандартного определения
     * и затем скорректировать его.
     *
     * @param resolver - Функция, принимающая запрос, заголовки и опционально `detect`.
     *                   Должна вернуть имя платформы (строка) или `null`.
     * @returns Тот же экземпляр приложения для цепочечных вызовов.
     *
     * @example
     * // Простейший резолвер, который для всех запросов использует платформу 'alisa'
     * bot.setPlatformResolver(() => 'alisa');
     *
     * @example
     * // Резолвер, который вызывает стандартное определение и при необходимости
     * // заменяет результат для конкретного заголовка.
     * bot.setPlatformResolver((query, headers, detect) => {
     *   const platform = detect?.(query, headers);
     *   if (platform === 'telegram' && headers?.['x-force-vk']) {
     *     return 'vk';
     *   }
     *   return platform;
     * });
     *
     * @example
     * // Полное переопределение: обработка запросов от собственного сервиса.
     * bot.setPlatformResolver((query) => {
     *   if (typeof query === 'object' && query?.source === 'my_service') {
     *     return 'my_platform';
     *   }
     *   return null;
     * });
     *
     * @remarks
     * - Резолвер может быть асинхронным, если это необходимо. Для этого просто объявите
     *   функцию как `async` и возвращайте `Promise<string | null>`. Фреймворк дождётся
     *   результата перед продолжением.
     * - Внутри резолвера можно модифицировать `query` или `headers`, если нужно повлиять
     *   на дальнейшую обработку (например, добавить недостающие поля).
     * - Если резолвер возвращает имя платформы, для которой нет зарегистрированного
     *   адаптера, фреймворк выбросит ошибку. Убедитесь, что нужный адаптер подключен.
     */
    setPlatformResolver(resolver: TPlatformResolver): this;
    /**
     * Позволяет установить свою реализацию для логирования
     * @param logger
     */
    setLogger(logger: ILogger | null): this;
    /**
     * Регистрирует команду — обработчик, срабатывающий при совпадении входящего текста с одним из шаблонов.
     *
     * Поиск команд оптимизирован:
     * 1. Сначала проверяется точное совпадение
     * 2. Если точного совпадения нет — выполняется последовательный перебор в порядке регистрации
     *
     * Первая совпавшая команда выполняется.
     *
     * @param {string} commandName - Уникальное имя команды (например, `'greeting'`). Используется для логирования и отладки.
     * @param {TSlots} slots - Массив шаблонов для сопоставления:
     *   - Если элемент — строка → ищется как подстрока (`text.includes(...)`).
     *   - Если элемент — RegExp → проверяется как регулярное выражение (`.test(text)`).
     *   - Параметр `isPattern` учитывается **только если в `slots` нет RegExp**.
     *   - При наличии хотя бы одного `RegExp`, `isPattern = false` игнорируется, и каждый элемент
     *     обрабатывается согласно своему типу.
     * @param {ICommandParam['cb']} cb - Обработчик команды. Принимает:
     *   - `text` — исходный текст от пользователя;
     *   - `controller` — экземпляр `BotController` для формирования ответа (кнопки, текст, шаги, данные и т.д.);
     *
     *   Поддерживает `async`.
     * @param {boolean} isPattern - Если `true` и в `slots` **нет RegExp**, все строки преобразуются в регулярные выражения.
     *                   ⚠️ Используйте с осторожностью: возможен ReDoS. Все RegExp проверяются на уязвимости.
     *
     * @example
     * Простая текстовая команда:
     * ```ts
     * bot.addCommand(
     *   'greeting',
     *   ['привет', 'здравствуй'],
     *   (cmd, ctrl) => {
     *     ctrl.text = 'Здравствуйте!';
     *   }
     * );
     * ```
     *
     * @example
     * Команда с регулярными выражениями:
     * ```ts
     * // Обработка чисел от 0 до 999
     * bot.addCommand(
     *   'number',
     *   ['\\b(\\d{0,3})\\b'],
     *   (cmd, ctrl) => {
     *     ctrl.text = `Вы ввели число: ${cmd}`;
     *   },
     *   true  // включаем поддержку регулярных выражений
     * );
     * ```
     *
     * @example
     * Команда с доступом к состоянию:
     * ```ts
     * bot.addCommand(
     *   'stats',
     *   ['статистика'],
     *   async (cmd, ctrl) => {
     *     if (ctrl) {
     *       // Доступ к пользовательским данным
     *       const visits = ctrl.userData?.visits || 0;
     *       ctrl.text = `Вы использовали приложение ${visits} раз`;
     *
     *       // Доступ к кнопкам и другим UI элементам
     *       ctrl.buttons
     *         .addBtn('Сбросить статистику')
     *         .addBtn('Закрыть');
     *     }
     *   }
     * );
     * ```
     *
     * @example
     * // Асинхронная команда (работа с API):
     * ```ts
     * bot.addCommand('weather', ['погода'], async (text, controller) => {
     *   const weather = await fetch('Какой-то сервис для получения погоды');
     *   controller.text = `Погода: ${await weather.text()}`;
     * });
     * ```
     *
     * @example
     * // Fallback: срабатывает, если ни одна команда не подошла:
     * ```ts
     * bot.addCommand('*', [], (text, controller) => {
     *   controller.text = `Извините, я не понял "${text}". Скажите "помощь" для списка команд.`;
     * });
     * ```
     *
     * @remarks
     * Поиск команд оптимизирован:
     * 1. Сначала проверяется точное совпадение
     * 2. Если точного совпадения нет — выполняется последовательный перебор
     *
     * При регистрации более 300 команд с регулярными выражениями
     * фреймворк автоматически объединяет их в группы для повышения производительности.
     *
     * При isPattern=true используются регулярные выражения JavaScript
     * В callback доступен весь функционал BotController
     * Можно использовать async функции в callback
     */
    addCommand<TBotController extends BotController = BotController>(commandName: string, slots: TSlots, cb: ICommandParam<TBotController>['cb'], isPattern?: boolean): this;
    /**
     * Удаляет зарегистрированную команду по имени
     * @param commandName - Имя команды
     */
    removeCommand(commandName: string): this;
    /**
     * Удаляет **все** зарегистрированные команды
     *
     * > ⚠️ Это **глобальная операция**: все сценарии станут недоступны.
     * > Используйте с осторожностью (например, при перезагрузке логики приложения).
     */
    clearCommands(): this;
    /**
     * Регистрирует обработчик для именованного шага диалога.
     *
     * Шаг — это часть **многошагового сценария** (например: "регистрация", "оформление заказа").
     * После вызова `ctx.thisIntentName = 'myStep'` в команде или другом шаге,
     * следующее сообщение пользователя будет обработано этим обработчиком.
     *
     * > 💡 Обработчик получает полный `BotController`, как и в командах:
     * > доступны `this.text`, `this.userData`, `this.buttons` и т.д.
     *
     * @param stepName — Уникальное имя шага (например, `'enter_email'`).
     * @param handler — Функция, вызываемая при получении сообщения в этом шаге.
     * @returns Текущий экземпляр `Bot` (для цепочки вызовов).
     *
     * @example
     * ```ts
     * bot.addCommand('start', ['начать'], (_, ctx) => {
     *      ctx.text = 'Готовы начать приключение?';
     *      ctx.buttons.addBtn('Да').addBtn('Нет');
     *      ctx.thisIntentName = 'confirm';
     * });
     * bot.addStep('confirm', (ctx) => {
     *   if (ctx.userCommand === 'да') {
     *     ctx.text = 'Отлично! Добро пожаловать.';
     *   } else {
     *     ctx.text = 'Извините, вход запрещён.';
     *     ctx.thisIntentName = 'goodbye'; // переходим к другому шагу
     *   }
     * });
     * ```
     * @example
     * ```ts
     * // Пример многошаговой формы
     * bot.addCommand('order', ['заказать'], (_, ctx) => {
     *     ctx.text = 'Введите ваше имя:';
     *     ctx.thisIntentName = 'step_name';
     * });
     *
     * bot.addStep('step_name', (ctx) => {
     *     ctx.userData.name = ctx.userCommand;
     *     ctx.text = `Приятно познакомиться, ${ctx.userData.name}! Теперь введите email:`;
     *     ctx.thisIntentName = 'step_email';
     * });
     *
     * bot.addStep('step_email', (ctx) => {
     *     ctx.userData.email = ctx.userCommand;
     *     ctx.text = `Заказ оформлен! Имя: ${ctx.userData.name}, Email: ${ctx.userData.email}`;
     *     ctx.thisIntentName = null; // сбрасываем шаг
     * });
     * ```
     */
    addStep<TBotController extends BotController = BotController>(stepName: string, handler: IStepParam<TBotController>['cb']): this;
    /**
     * Удаляет зарегистрированный шаг по имени.
     *
     * После удаления шаг больше не будет обрабатываться, даже если активен у пользователя.
     * (Рекомендуется завершать активные сценарии через `ctx.clearStep()` перед удалением.)
     *
     * @param stepName — Имя шага для удаления.
     * @returns Текущий экземпляр `Bot`.
     */
    removeStep(stepName: string): this;
    /**
     * Удаляет **все** зарегистрированные шаги.
     *
     * > ⚠️ Это **глобальная операция**: все сценарии станут недоступны.
     * > Используйте с осторожностью (например, при перезагрузке логики приложения).
     *
     * @returns Текущий экземпляр `Bot`.
     */
    clearSteps(): this;
    /**
     * Удаляет **все** зарегистрированные платформы, плагины и middleware службы.
     *
     * > ⚠️ Это **глобальная операция**: все сценарии станут недоступны.
     * > Используйте с осторожностью (например, при перезагрузке логики приложения).
     *
     * @returns Текущий экземпляр `Bot`.
     */
    clearUse(): this;
    /**
     * Устанавливает режим работы приложения
     *
     * @param {'dev' | 'prod' | 'strict_prod'} appMode - Режим работы:
     * - 'dev': подробные логи, отладочная информация, отключена проверка ReDoS
     * - 'prod': минимальные логи, производительность, НО небезопасные RegExp всё равно регистрируются
     * - 'strict_prod': строгая проверка безопасности — любая RegExp с потенциальным ReDoS отклоняется с ошибкой
     *
     * ⚠️ ВАЖНО: В продакшене всегда используйте 'strict_prod' для защиты от атак через регулярные выражения.
     * Режим 'prod' оставлен для обратной совместимости, но небезопасен.
     *
     * @example
     * // Для продакшена (обязательно!)
     * bot.setAppMode('strict_prod');
     *
     * // Для разработки
     * bot.setAppMode('dev');
     * @param appMode
     */
    setAppMode(appMode: TAppMode): this;
    /**
     * Позволяет заменить встроенный механизм сопоставления команд на **кастомный алгоритм поиска**.
     *
     *  По умолчанию `umbot` использует **оптимизированный поиск**:
     *  1. Сначала проверяется точное совпадение
     *  2. Если точного совпадения нет — выполняется последовательный перебор с поддержкой:
     *      - подстрок (`includes`),
     *      - простых регулярных выражений.
     *
     * Это обеспечивает **предсказуемость**, **простоту отладки** и **соответствие поведению большинства платформ**:
     * первая совпавшая команда (в порядке регистрации) — выигрывает.
     *
     * Однако при:
     * - количестве команд >1000,
     * - высокой нагрузке (>1000 RPS),
     * - необходимости в fuzzy-поиске или сложной маршрутизации,
     * вы можете подключить оптимизированный resolver.
     *
     * @param resolver - Функция вида `(userText: string, commands: Map<string, ICommand>) => string | null`.
     *                    Должна вернуть имя команды или `null`, если совпадений нет.
     *
     * @example
     * ```ts
     * // Пример: кэширование частых запросов
     * const cache = new Map<string, string | null>();
     * bot.setCustomCommandResolver((text, commands) => {
     *   if (cache.has(text)) return cache.get(text)!;
     *
     *   for (const [name, cmd] of commands) {
     *     if (cmd.slots && cmd.slots.some(slot => typeof slot === 'string' && text.includes(slot))) {
     *       cache.set(text, name);
     *       return name;
     *     }
     *   }
     *   cache.set(text, null);
     *   return null;
     * });
     * ```
     *
     * @remarks
     * **Рекомендации при реализации resolver'а:**
     * - Сохраняйте **порядок регистрации команд**, если логика зависит от приоритета.
     * - Используйте **кэширование** для часто встречающихся фраз (но учитывайте потребление памяти).
     * - Для fuzzy-поиска — рассмотрите `fuse.js`, `natural` или trie-структуры.
     * - При работе с регулярными выражениями **обязательно проверяйте их на ReDoS**.
     * - Избегайте тяжёлых синхронных операций — они блокируют event loop.
     */
    setCustomCommandResolver(resolver: TCommandResolver): this;
    /**
     * Задаёт **инфраструктурную конфигурацию** приложения: подключение к БД, загрузку `.env`, и другие
     * настройки, связанные с окружением выполнения (а не с бизнес-логикой приложения).
     *
     * > 🔒 **Безопасность**: никогда не храните секреты (пароли, токены, API-ключи) прямо в коде.
     * > Всегда используйте `.env`-файлы или переменные окружения.
     *
     * @param {IAppConfig} config - Конфигурация приложения
     *
     * @example
     * ```ts
     * // Конфигурация с базой данных
     * bot.setAppConfig({
     *   db: {
     *     host: 'localhost',
     *     database: 'bot_db',
     *     user: 'user',
     *     pass: 'password'
     *   }
     * });
     *
     *
     * @remarks
     * Важно! Чувствительные данные рекомендуется сохранять в .env файл, передав путь к нему:
     * ```ts
     * bot.setAppConfig({
     *     env: './.env', // путь до файла
     * });
     * ```
     */
    setAppConfig(config: Partial<IAppConfig>): this;
    /**
     * Возвращает контекст приложения — центральный объект для расширенной настройки фреймворка.
     *
     * **Когда использовать:**
     * - Замена HTTP-клиента: `bot.getAppContext().httpClient = customFetch`
     * - Доступ к зарегистрированным адаптерам: `bot.getAppContext().platforms`
     * - Настройка метрик и логирования
     *
     * **Пример:**
     * ```ts
     * // Добавление таймаутов к запросам
     * const customFetch: THttpClient = async (url, init) => {
     *   const controller = new AbortController();
     *   const timeout = setTimeout(() => controller.abort(), 5000);
     *   return fetch(url, { ...init, signal: controller.signal });
     * };
     *
     * bot.getAppContext().httpClient = customFetch;
     *
     * ⚠️ Важно: Не модифицируйте внутренние поля контекста напрямую (например, commands, steps). Используйте публичные методы addCommand(), addStep().
     */
    getAppContext(): AppContext;
    /**
     * Задаёт параметры, управляющие **логикой приложения** на всех платформах.
     *
     * Сюда входят:
     * - список интентов по умолчанию (`help`, `welcome` и др.),
     * - тексты ответов по умолчанию (`welcome_text`, `help_text`, `empty_text`),
     * - другие настройки, не зависящие от конкретной платформы
     *
     * @param {IAppParam} params - Параметры платформы
     *
     * @example
     * ```ts
     * // Базовая настройка
     * bot.setPlatformParams({
     *   intents: [{
     *     name: 'help',
     *     slots: ['помощь', 'справка']
     *   }],
     *   welcome_text: 'Привет! Я ваш помощник.',
     *   help_text: 'Скажите "помощь", чтобы увидеть команды.',
     *   empty_text: 'Извините, я не понял.'
     * });
     * ```
     */
    setPlatformParams(params: IAppParam): this;
    /**
     * Устанавливает контроллер, метод `action()` которого вызывается **после обработки каждого запроса** —
     * независимо от того, была ли распознана команда, активен ли шаг сценария, или обработан базовый интент.
     *
     * Метод `action()` получает флаги `isCommand` и `isStep`, чтобы вы могли:
     * - добавить общую логику (аналитика, логирование, трассировка);
     * - модифицировать ответ глобально (например, добавить рекламу, кнопку "Оценить");
     * - применить кросс-функциональные правила (rate limiting, мутации текста и т.д.);
     *
     * > 💡 **Рекомендация**: основную бизнес-логику размещайте в командах (`addCommand`) и шагах (`addStep`),
     * > а в `action()` — только **сквозную** логику, которую не хочется дублировать.
     *
     * Контроллер по умолчанию уже обрабатывает интенты `welcome`, `help` и `fallback`,
     * но вы можете заменить его, если нужно кастомное поведение.
     *
     * @param {BotController<TUserData>} fn - Экземпляр контроллера, наследующий `BotController<TUserData>`
     *
     * @example
     * ```ts
     * class MyController extends BotController {
     *   public action(intentName: string): void {
     *     switch (intentName) {
     *       case 'greeting':
     *         this.text = 'Привет!';
     *         break;
     *       case 'help':
     *         this.text = 'Чем могу помочь?';
     *         break;
     *     }
     *   }
     * }
     *
     * bot.initBotController(MyController);
     * ```
     *
     * @example
     * ```ts
     * // Добавление рекламы ко всем ответам
     * class MyController extends BotController {
     *   public action(
     *     intentName: string | null,
     *     isCommand: boolean = false,
     *     isStep: boolean = false
     *   ): void {
     *     // Добавим кнопку "Подписаться" везде, кроме шагов
     *     if (!isStep) {
     *       this.buttons.addBtn('Подписаться на рассылку', 'http://localhost');
     *     }
     *
     *     // Логирование
     *     console.log(`Обработано: ${isCommand ? 'команда' : isStep ? 'шаг' : 'интент'} – ${intentName}`);
     *   }
     * }
     *
     * bot.initBotController(MyController);
     * ```
     */
    initBotController(fn: TBotControllerClass<TUserData>): this;
    /**
     * Устанавливает контент запроса.
     * Используется для передачи данных от пользователя в платформу.
     * Не рекомендуется использовать напрямую, использовать только в крайнем случае, либо для тестов
     *
     * @param {TBotContent} content - Контент запроса
     *
     * @example
     * ```ts
     * // Установка текстового сообщения
     * bot.setContent('Привет!');
     *
     * // Установка JSON-данных
     * bot.setContent({
     *   request: {
     *     command: 'привет',
     *     original_utterance: 'Привет, мир!'
     *   }
     * });
     * ```
     */
    setContent(content: TBotContent): void;
    /**
     * Очищает состояние пользователя
     */
    protected _clearState(botController: BotController): void;
    /**
     * Регистрирует middleware, вызываемый **до** выполнения `BotController.action()`.
     *
     * Middleware получает доступ к полному `BotController` (включая `text`, `isEnd`, `userData`, `buttons` и т.д.)
     * и может:
     * - Модифицировать контекст
     * - Прервать выполнение (если не вызвать `next()`)
     * - Выполнить логирование, tracing, rate limiting и др.
     *
     * @example
     * // Глобальный middleware (для всех платформ)
     * bot.use(async (ctx, next) => {
     *   console.log('Запрос от:', ctx.appType);
     *   await next();
     * });
     *
     * @param fn - Middleware-функция
     * @returns Текущий экземпляр `Bot` для цепочки вызовов
     */
    use(fn: MiddlewareFn): this;
    /**
     * Регистрирует middleware, вызываемый только для указанной платформы.
     *
     * @example
     * // Только для Алисы
     * bot.use(T_ALISA, async (ctx, next) => {
     *   if (!ctx.appContext.requestObject?.session?.user_id) {
     *     ctx.text = 'Некорректный запрос';
     *     ctx.isEnd = true;
     *     // next() не вызывается → action() не запускается
     *     return;
     *   }
     *   await next();
     * });
     *
     * @param platform - Идентификатор платформы (`alisa`, `telegram`, `vk`, и т.д.)
     * @param fn - Middleware-функция
     * @returns Текущий экземпляр `Bot`
     */
    use(platform: TAppType, fn: MiddlewareFn): this;
    /**
     * Регистрирует плагин — объект, расширяющий функциональность приложения.
     *
     * Плагин может быть как функцией, так и классом.
     * Если он реализован как метод, то должен быть указан флаг isPlugin.
     * В случае когда используется класс, то должен быть реализован метод `init(appContext: AppContext)`
     *
     * @param plugin — Объект плагина, совместимый с `TPlugin`.
     * @returns Текущий экземпляр `Bot`.
     *
     * @example
     * import {AlisaAdapter} from 'umbot/plugins'
     * bot.use(new AlisaAdapter());
     */
    use(plugin: TPlugin): this;
    /**
     * Установка контроллера. Используется только для тестирования
     * @param botController
     * @protected
     */
    protected _setBotController(botController: BotController<TUserData>): void;
    /**
     * Получение контроллера приложения
     * Не использовать!
     * @private
     */
    getBotController(): BotController<TUserData> | null;
    /**
     * Выполняет непосредственную обработку входящего запроса от платформы.
     * Этот метод **не запускает HTTP-сервер** и **не обрабатывает HTTP-запросы напрямую** —
     * он принимает уже распарсенные данные и возвращает результат обработки.
     *
     * Обычно вызывается **внутри {@link webhookHandle}**, но может использоваться напрямую,
     * если вы реализуете собственный обработчик запросов, тестируете логику приложения
     * или запускаете его вне HTTP-контекста (например, из консоли или очереди сообщений).
     *
     * @param {TAppType | null} [appType] - Тип приложения. Если не указан, будет определен автоматически в зависимости от запроса.
     * @param {string | object} [content] - Входные данные для обработки (например, текст сообщения или объект запроса).
     * @returns {Promise<TRunResult>} Результат обработки запроса
     * @throws {Error} Если не удаётся определить платформу или отсутствуют данные для обработки.
     *
     * @example
     * ```ts
     * // Обработка запроса
     * const result = await bot.run();
     * console.log(result);
     * ```
     */
    run(appType?: TAppType | null, content?: string | object | null): Promise<TRunResult>;
    /**
     * Обрабатывает входящий webhook-запрос от поддерживаемой платформы (Telegram, VK, Алиса и др.).
     * Метод автоматически распознаёт платформу по заголовкам или телу запроса и делегирует обработку
     * соответствующему адаптеру. Ответ отправляется автоматически через переданный объект `res`.
     *
     * @param req - Объект входящего запроса (IncomingMessage или совместимый)
     * @param res - Объект ответа (ServerResponse или совместимый)
     * @param responseCb - Callback, для пользовательской обработки ответа пользователю. Стоит использовать в том случае, если есть необходимость переопределить стандартный ответ фреймворка.
     * Если передан, ВЫ ДОЛЖНЫ вызвать res.end() самостоятельно.
     * Без колбэка фреймворк автоматически завершит ответ через res.end().
     *
     * @example
     * ```ts
     * // Использование с Express
     * import express from 'express';
     * const app = express();
     * app.use(express.json());
     *
     * const bot = new Bot();
     *
     * app.post('/webhook', (req, res) => bot.webhookHandle(req, res));
     * ```
     * @example
     * // Использование с встроенным HTTP-сервером Node.js
     * import { createServer } from 'http';
     *
     * const bot = new Bot();
     * const server = createServer((req, res) => {
     *   if (req.method === 'POST' && req.url === '/webhook') {
     *     bot.webhookHandle(req, res);
     *   } else {
     *     res.statusCode = 404;
     *     res.end();
     *   }
     * });
     * server.listen(3000);
     * @example
     * ```ts
     * // Пример с переопределением ответа
     * import { createServer } from 'http';
     *
     * const bot = new Bot();
     * const server = createServer((req, res) => {
     *   if (req.method === 'POST' && req.url === '/webhook') {
     *     // В случае если вернулся статус отличный от 200, вернет содержимое какой-то страницы.
     *     bot.webhookHandle(req, res, (_reg: IncomingMessage, _res: ServerResponse, state: IBotResponseState) => {
     *          if (state.statusCode === 200) {
     *              return state.defaultSend(_res, state);
     *          }
     *          res.statusCode = 200;
     *          res.end(...);// Какое-то содержимое страницы
     *     });
     *   } else {
     *     res.statusCode = 404;
     *     res.end();
     *   }
     * });
     * server.listen(3000);
     *
     * ```
     */
    webhookHandle(req: IncomingMessage, res: ServerResponse, responseCb?: TBotResponseCb): Promise<void>;
    /**
     * Запускает встроенный HTTP-сервер на указанном хосте и порту для приёма webhook-запросов
     * от поддерживаемых платформ. Сервер использует нативный `http.createServer`.
     *
     * Метод возвращает экземпляр `http.Server`, что позволяет, например, корректно
     * остановить сервер или добавить обработчики событий (`'listening'`, `'error'` и т.д.).
     *
     * Если требуется интеграция с фреймворком (например, Express, Fastify и др.),
     * рекомендуется использовать {@link webhookHandle} как middleware-обработчик.
     *
     * @see webhookHandle
     *
     * @param {string} hostname - Имя хоста
     * @param {number} port - Порт
     * @param responseCb - Callback, для пользовательской обработки ответа пользователю. Стоит использовать в том случае, если есть необходимость переопределить стандартный ответ фреймворка.
     *
     * @example
     * ```ts
     * // Запуск встроенного сервера
     * const bot = new Bot();
     * bot.start('0.0.0.0', 8080);
     *
     * // Интеграция с Express (вместо встроенного сервера)
     * import express from 'express';
     * import { Bot } from 'umbot';
     *
     * const bot = new Bot();
     * const app = express();
     * app.use(express.json());
     * app.post('/webhook', (req, res) => bot.webhookHandle(req, res));
     *
     * app.listen(3000, () => {
     *   console.log('Bot listening on port 3000');
     * });
     * ```
     * ```ts
     * // Пример с переопределением ответа
     * const bot = new Bot();
     * // В случае если вернулся статус отличный от 200, вернет содержимое какой-то страницы.
     * bot.start('0.0.0.0', 8080, (reg: IncomingMessage, _res: ServerResponse, state: IBotResponseState) => {
     *      if (state.statusCode === 200) {
     *          return state.defaultSend(_res, state);
     *      }
     *      res.statusCode = 200;
     *      res.end(...);// Какое-то содержимое страницы
     * });
     * ```
     */
    start(hostname?: string, port?: number, responseCb?: TBotResponseCb): Server;
    /**
     * Корректно завершает работу встроенного HTTP-сервера (если он был запущен через {@link start}).
     * Ожидает завершения всех текущих запросов, освобождает сетевые ресурсы и отменяет
     * все активные асинхронные операции, связанные с жизненным циклом приложения.
     *
     * Метод безопасен для повторного вызова.
     *
     * @returns {Promise<void>} Завершается, когда сервер остановлен и все ресурсы освобождены.
     *
     * @example
     * ```ts
     * const bot = new Bot();
     * bot.start('localhost', 3000);
     *
     * // ... позже, при завершении приложения
     * await bot.close();
     * ```
     */
    close(): Promise<void>;
    /**
     * Отправка текста пользователю
     * Этот метод используется для активных рассылок — когда голосовой навык или чат-бот инициирует диалог первым (например, уведомление).
     * В методе реализована механика преобразования текстового значения `controllerOrText` в контроллер, а также базовый механизм для отправки ответа.
     *
     * Если платформа не поддерживает возможность начать диалог самостоятельно, то вернется false
     * @param userId Ид пользователя, которому нужно отправить сообщение
     * @param controllerOrText Контроллер приложения или текст. Если необходимо отправить просто текст, можно передать строку, в случае, если необходимо передать картинку звук и тд, то необходимо корректно заполнить контроллер.
     * @param platform Платформа, на которую необходимо отправить запрос
     */
    send(userId: string | number, controllerOrText: BotController | string, platform: TAppType): Promise<unknown | boolean>;
}
