# Firebase Cloud Messaging (FCM) Integration

## Обзор

Android приложение использует **Firebase Cloud Messaging (FCM)** для push-уведомлений о новых сообщениях.

## Архитектура

### Клиент (Android)

1. **При старте приложения** (`MainActivity.kt`):

   - Инициализируется Firebase
   - Получается FCM токен
   - Токен отправляется на сервер через протокол

2. **При получении нового токена** (`RosettaFirebaseMessagingService.kt`):

   - Вызывается `onNewToken()`
   - Новый токен отправляется на сервер

3. **При получении push-уведомления** (`RosettaFirebaseMessagingService.kt`):
   - Вызывается `onMessageReceived()`
   - Показывается системное уведомление
   - При клике открывается соответствующий чат

### Протокол

**Packet ID: 0x0A - PacketPushToken**

Формат пакета:

```
[PacketID: 0x0A (2 bytes)]
[privateKey: String]
[publicKey: String]
[pushToken: String]
[platform: String] // "android" или "ios"
```

### Сервер

Сервер должен:

1. Получить `PacketPushToken` от клиента
2. Сохранить в БД связку: `publicKey -> fcmToken`
3. При получении нового сообщения для пользователя:
   - Найти FCM токен по `publicKey` получателя
   - Отправить push через FCM HTTP API

## Настройка Firebase

### 1. Создать Firebase проект

1. Перейти на [Firebase Console](https://console.firebase.google.com/)
2. Создать новый проект или выбрать существующий
3. Добавить Android приложение

### 2. Настройка Android app

**Package name:** `com.rosetta.messenger`

1. В Firebase Console → Project Settings → General
2. Скачать `google-services.json`
3. Поместить файл в `rosetta-android/app/google-services.json`

### 3. Структура google-services.json

```json
{
  "project_info": {
    "project_number": "YOUR_PROJECT_NUMBER",
    "project_id": "your-project-id",
    "storage_bucket": "your-project-id.appspot.com"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:YOUR_PROJECT_NUMBER:android:xxxxx",
        "android_client_info": {
          "package_name": "com.rosetta.messenger"
        }
      },
      "oauth_client": [],
      "api_key": [
        {
          "current_key": "YOUR_API_KEY"
        }
      ],
      "services": {
        "appinvite_service": {
          "other_platform_oauth_client": []
        }
      }
    }
  ],
  "configuration_version": "1"
}
```

### 4. Получить Server Key

1. Firebase Console → Project Settings → Cloud Messaging
2. Скопировать **Server Key** (Legacy)
3. Использовать на сервере для отправки уведомлений

## Отправка Push-уведомлений с сервера

### FCM HTTP v1 API (рекомендуется)

```bash
POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json

{
  "message": {
    "token": "FCM_DEVICE_TOKEN_FROM_CLIENT",
    "notification": {
      "title": "Имя отправителя",
      "body": "Текст сообщения"
    },
    "data": {
      "type": "new_message",
      "sender_public_key": "SENDER_PUBLIC_KEY",
      "sender_name": "Имя отправителя",
      "message_preview": "Текст сообщения"
    },
    "android": {
      "priority": "HIGH",
      "notification": {
        "channel_id": "messages",
        "sound": "default",
        "notification_priority": "PRIORITY_HIGH"
      }
    }
  }
}
```

### Legacy FCM API (проще для начала)

```bash
POST https://fcm.googleapis.com/fcm/send
Authorization: key=YOUR_SERVER_KEY
Content-Type: application/json

{
  "to": "FCM_DEVICE_TOKEN_FROM_CLIENT",
  "notification": {
    "title": "Имя отправителя",
    "body": "Текст сообщения",
    "sound": "default"
  },
  "data": {
    "type": "new_message",
    "sender_public_key": "SENDER_PUBLIC_KEY",
    "sender_name": "Имя отправителя",
    "message_preview": "Текст сообщения"
  },
  "priority": "high",
  "android": {
    "priority": "HIGH",
    "notification": {
      "channel_id": "messages"
    }
  }
}
```

## Пример серверной логики (Node.js)

```javascript
const admin = require("firebase-admin");

// Инициализация Firebase Admin SDK
const serviceAccount = require("./path/to/serviceAccountKey.json");
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// База данных с токенами (пример)
const userTokens = new Map(); // publicKey -> fcmToken

// Обработка PacketPushToken (0x0A)
function handlePushToken(packet) {
  const { publicKey, pushToken, platform } = packet;

  console.log(`📱 Saving FCM token for user ${publicKey.slice(0, 10)}...`);
  userTokens.set(publicKey, pushToken);
}

// Отправка push-уведомления
async function sendPushNotification(
  recipientPublicKey,
  senderPublicKey,
  senderName,
  messageText
) {
  const fcmToken = userTokens.get(recipientPublicKey);

  if (!fcmToken) {
    console.log("⚠️ No FCM token for user");
    return;
  }

  const message = {
    token: fcmToken,
    notification: {
      title: senderName,
      body: messageText,
    },
    data: {
      type: "new_message",
      sender_public_key: senderPublicKey,
      sender_name: senderName,
      message_preview: messageText,
    },
    android: {
      priority: "HIGH",
      notification: {
        channelId: "messages",
        sound: "default",
        priority: "PRIORITY_HIGH",
      },
    },
  };

  try {
    const response = await admin.messaging().send(message);
    console.log("✅ Push notification sent:", response);
  } catch (error) {
    console.error("❌ Error sending push:", error);

    // Если токен невалиден - удаляем из БД
    if (
      error.code === "messaging/invalid-registration-token" ||
      error.code === "messaging/registration-token-not-registered"
    ) {
      userTokens.delete(recipientPublicKey);
    }
  }
}

// Когда приходит PacketMessage
function handleNewMessage(packet) {
  const { fromPublicKey, toPublicKey, content } = packet;

  // Отправляем push получателю (если он не онлайн)
  sendPushNotification(toPublicKey, fromPublicKey, "User", "New message");
}
```

## Тестирование

### 1. Проверка токена

```kotlin
// В логах Android Studio должно быть:
🔔 FCM token: XXXXXXXXXXXX...
```

### 2. Тест через Firebase Console

1. Firebase Console → Cloud Messaging
2. Send test message
3. Вставить FCM токен из логов
4. Отправить

### 3. Проверка формата пакета

```
Packet 0x0A должен содержать:
- PacketID: 0x0A (10 в decimal)
- privateKey: хеш приватного ключа
- publicKey: публичный ключ пользователя
- pushToken: FCM токен устройства
- platform: "android"
```

## Troubleshooting

### Токен не получается

1. Проверить `google-services.json` в `app/google-services.json`
2. Проверить package name совпадает: `com.rosetta.messenger`
3. Rebuild проект
4. Проверить Google Play Services на устройстве

### Уведомления не приходят

1. Проверить разрешение на уведомления (Android Settings)
2. Проверить Server Key на сервере
3. Проверить FCM токен актуален
4. Проверить формат JSON в FCM API запросе

### Уведомления приходят, но не открывают чат

Проверить data payload содержит `sender_public_key`

## Полезные ссылки

- [Firebase Console](https://console.firebase.google.com/)
- [FCM Documentation](https://firebase.google.com/docs/cloud-messaging)
- [Android Setup Guide](https://firebase.google.com/docs/cloud-messaging/android/client)
- [FCM HTTP Protocol](https://firebase.google.com/docs/cloud-messaging/http-server-ref)
