# Бот-напоминание о записи (MAX + Telegram + Медиалог + Bitrix24)

Реализация по ТЗ «Бот для оповещения пациента о записи». Клиника шлёт пациенту
напоминание о приёме с 4 кнопками; по нажатию бот меняет статус в Медиалоге или
передаёт диалог оператору открытой линии Bitrix24. Работает **и в MAX, и в Telegram**.

## Архитектура
Транспорт вынесен за интерфейс `Messenger`, поэтому вся бизнес-логика общая —
`ReminderBot` один на обе платформы. MAX и Telegram отличаются только реализацией
отправки/разбора:

```
ReminderBot ──> Messenger (интерфейс)
                  ├── MaxMessenger      (MaxApi)
                  └── TelegramMessenger  (TelegramApi)
ReminderBot ──> MedialogApi   (api_v2.php)        — общий
ReminderBot ──> PatientStore  (platform+chat↔пациент) — общий
ReminderBot ──> OperatorHandoff (Bitrix24)         — общий, выбирает линию по платформе
```

Добавить третий мессенджер = написать ещё одну реализацию `Messenger`, логику не трогая.

## Сценарий
1. Пациент запускает бота (MAX или TG) → делится контактом → ищем его в Медиалоге
   по телефону (`searchPacients`) → запоминаем `(платформа, chat_id) ↔ PATIENTS_ID`.
   *MAX/TG не дают писать по номеру — только тем, кто запустил бота, поэтому привязка обязательна.*
2. Планировщик/Б24 вызывает `send_reminder.php <planning_id>` → бот сам выбирает
   платформу пациента и шлёт напоминание с 4 кнопками.
3. Пациент жмёт кнопку → действие.

## Карта «кнопка → действие → метод»
| Кнопка | Действие | Вызов |
|---|---|---|
| Подтвердить запись | статус подтверждения (STATUS2) | Медиалог `updateCall(planning_id, status)` |
| Отменить запись | CANCELLED=1, STATUS=1 | Медиалог `editStatus(planning_id)` |
| Перенести запись | оператор Б24, «Прошу перенести запись» | открытая линия Bitrix24 |
| Соединение с оператором | оператор Б24, «Нужна консультация» | открытая линия Bitrix24 |

## Различия платформ (учтены в коде)
| | MAX | Telegram |
|---|---|---|
| Кнопки | inline `payload` | inline `callback_data` |
| Запрос контакта | inline `request_contact` | reply-клавиатура `request_contact` |
| Проверка контакта | HMAC-SHA256(token, vcf) == hash | `contact.user_id == from.id` |
| Ответ на кнопку | `answerCallback` (тост + сообщение) | `answerCallbackQuery` (тост) + отдельный `sendMessage` |
| Приём событий | webhook / long polling | webhook / long polling |

## Запуск
1. Токены: `MAX_BOT_TOKEN` (или в `config.php`) и `TG_BOT_TOKEN` (от @BotFather).
   Адрес Медиалога и данные клиники — в `config.php`.
2. Проверка токенов: `php cli.php max:me`, `php cli.php tg:me`.
3. Разработка (long polling):
   - MAX: `php cli.php max:poll`
   - Telegram: `php cli.php tg:delwebhook` затем `php cli.php tg:poll`
4. Прод (webhook):
   - MAX: указать `max.webhook_url` → `php cli.php max:subscribe`
   - Telegram: указать `tg.webhook_url` → `php cli.php tg:setwebhook`
5. Тест напоминания без МИС:
   `php send_reminder.php manual tg <chat_id> 500 "21.05.2026" "11:30" "гинеколога" "Ковалёва Е. И." "Натощак"`
6. Боевая отправка: `php send_reminder.php <planning_id>`
   (сверить поля: `php send_reminder.php dump <planning_id>`).

## Что уточнить/подставить
- **STATUS2 при подтверждении** (`config → medialog.status_confirmed`) — в БД может быть код, а не строка. Уточни у того, кто ведёт Медиалог.
- **Поля `getPlannigId`** — маппинг в `send_reminder.php → mapAppointment()`; сверь через `dump` и поправь имена, если отличаются. Специальность («гинеколога») — справочник отдаёт код, при необходимости добавь маппинг код→слово (род. падеж).
- **Текст подготовки** — в Медиалоге привязан к услуге (`getPriceServices`, «инструкция подготовки»). Сейчас берётся из поля записи, если МИС его отдаёт.
- **Bitrix24** (`config → bitrix24`) — нужен входящий вебхук портала и для КАЖДОГО мессенджера свои `connector_id`/`line_id` (операторы привязаны к конкретному каналу). Каркас на `imconnector.send.messages`; точный метод/поток зависят от твоей настройки коннектора. Пустой webhook → передача оператору пишется в лог (бот работает).

## Подводные камни
- **MAX**: домен `platform-api2.max.ru`, токен заголовком; webhook с 25.05.2026 — только HTTPS + доверенный сертификат (Минцифры); структуру апдистов один раз сверь по `bot.log`; порядок аргументов HMAC сверь на живом контакте.
- **Telegram**: webhook и long polling несовместимы — перед `tg:poll` сделай `tg:delwebhook`; `callback_data` ≤ 64 байт (наши payload крошечные); webhook требует валидный HTTPS-сертификат.
- **Медиалог**: `api_v2.php` по HTTP (без TLS) и закрыт по VPN/IP — хост бота должен быть в разрешённой сети. В присланной доке Backend пароль БД лежит открыто в их `config.php` — бот его не использует, но на будущее стоит вынести в env.

## WhatsApp
По ТЗ — через Wazzup24 (платно), вне текущего объёма. При желании добавляется
ещё одной реализацией `Messenger` поверх API Wazzup24.

## Структура
```
config.php              — MAX, Telegram, Медиалог, клиника, Б24, пути
bootstrap.php           — сборка + фабрика makeBot('max'|'tg')
webhook.php             — вебхук MAX
webhook_tg.php          — вебхук Telegram
send_reminder.php       — рассылка (cron/Б24): авто | dump | manual
cli.php                 — max:* и tg:* команды
src/Messenger.php       — интерфейс транспорта
src/MaxApi.php          — клиент MAX
src/MaxMessenger.php    — MAX как Messenger
src/TelegramApi.php     — клиент Telegram Bot API
src/TelegramMessenger.php — Telegram как Messenger
src/MedialogApi.php     — клиент Медиалога (api_v2.php)
src/ReminderBot.php     — общая логика: напоминание, 4 кнопки, привязка
src/OperatorHandoff.php — передача оператору Б24 (по платформе)
src/PatientStore.php    — связка (платформа+chat) ↔ пациент
src/Phone.php           — нормализация телефонов
src/Keyboard.php        — inline-клавиатура MAX
```
