# FCM Token Registration Guide

This guide explains how to register FCM (Firebase Cloud Messaging) tokens for admins so they can receive push notifications.

## Overview

To receive notifications, admins must first register their FCM token with the API. The FCM token is a unique identifier for each device/app instance that Firebase uses to send push notifications.

## API Endpoint

### Register FCM Token

**Endpoint:** `POST /admin/register_fcm_token`

**Authentication:** Required (Admin authentication token)

**Headers:**
```
Authorization: Bearer <admin_auth_token>
Content-Type: application/json
```

**Request Body:**
```json
{
  "fcm_token": "YOUR_FCM_TOKEN_HERE"
}
```

**cURL Example:**
```bash
curl -X POST http://localhost:3000/admin/register_fcm_token \
  -H "Authorization: Bearer YOUR_ADMIN_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fcm_token": "dKx8s9fK...your_fcm_token_here..."
  }'
```

**Success Response (200):**
```json
{
  "status": "success",
  "message": "FCM token registered successfully",
  "data": {
    "admin_id": 1,
    "admin_name": "Admin User",
    "fcm_token_registered": true
  }
}
```

**Error Responses:**

**400 Bad Request** (Missing token):
```json
{
  "status": "error",
  "message": "Missing required field: fcm_token"
}
```

**401 Unauthorized** (Invalid or missing auth token):
```json
{
  "status": "error",
  "message": "Admin authentication required"
}
```

**500 Internal Server Error**:
```json
{
  "status": "error",
  "message": "Failed to register FCM token",
  "error": "Error details here"
}
```

## Step-by-Step Guide

### Step 1: Admin Login

First, the admin needs to log in to get an authentication token:

```bash
curl -X POST http://localhost:3000/admin/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "password",
    "company_id": 1
  }'
```

Response will include `auth_token`:
```json
{
  "status": "success",
  "message": "Login successful",
  "auth_token": "abc123xyz...",
  "admin": {
    "id": 1,
    "name": "Admin User",
    "username": "admin",
    "company_id": 1
  }
}
```

### Step 2: Get FCM Token from Mobile App

In your mobile app, get the FCM token from Firebase. The method depends on your framework:

#### React Native (with @react-native-firebase/messaging)

```javascript
import messaging from '@react-native-firebase/messaging';

async function getFCMToken() {
  try {
    // Request permission (iOS)
    const authStatus = await messaging().requestPermission();
    const enabled =
      authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
      authStatus === messaging.AuthorizationStatus.PROVISIONAL;

    if (enabled) {
      // Get FCM token
      const fcmToken = await messaging().getToken();
      console.log('FCM Token:', fcmToken);
      return fcmToken;
    } else {
      console.log('Notification permission not granted');
      return null;
    }
  } catch (error) {
    console.error('Error getting FCM token:', error);
    return null;
  }
}
```

#### Flutter (with firebase_messaging)

```dart
import 'package:firebase_messaging/firebase_messaging.dart';

Future<String?> getFCMToken() async {
  try {
    FirebaseMessaging messaging = FirebaseMessaging.instance;
    
    // Request permission
    NotificationSettings settings = await messaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );
    
    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      // Get FCM token
      String? token = await messaging.getToken();
      print('FCM Token: $token');
      return token;
    } else {
      print('Notification permission not granted');
      return null;
    }
  } catch (e) {
    print('Error getting FCM token: $e');
    return null;
  }
}
```

#### Android Native (Java/Kotlin)

```java
FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
            if (!task.isSuccessful()) {
                Log.w(TAG, "Fetching FCM registration token failed", task.getException());
                return;
            }

            // Get new FCM registration token
            String token = task.getResult();
            Log.d(TAG, "FCM Token: " + token);
            // Use this token to register with your API
        }
    });
```

#### iOS Native (Swift)

```swift
import FirebaseMessaging

Messaging.messaging().token { token, error in
  if let error = error {
    print("Error fetching FCM registration token: \(error)")
  } else if let token = token {
    print("FCM registration token: \(token)")
    // Use this token to register with your API
  }
}
```

### Step 3: Register FCM Token with API

Once you have the FCM token, register it with the API:

#### React Native Example

```javascript
async function registerFCMToken(adminAuthToken, fcmToken) {
  try {
    const response = await fetch('http://your-api.com/admin/register_fcm_token', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${adminAuthToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        fcm_token: fcmToken
      })
    });

    const result = await response.json();
    
    if (result.status === 'success') {
      console.log('FCM token registered successfully');
      return true;
    } else {
      console.error('Failed to register FCM token:', result.message);
      return false;
    }
  } catch (error) {
    console.error('Error registering FCM token:', error);
    return false;
  }
}

// Usage after admin login
const adminAuthToken = '...'; // From login response
const fcmToken = await getFCMToken();
if (fcmToken) {
  await registerFCMToken(adminAuthToken, fcmToken);
}
```

#### Complete React Native Flow

```javascript
import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

class AdminNotificationService {
  constructor() {
    this.adminAuthToken = null;
    this.setupTokenRefresh();
  }

  // Setup token refresh listener
  setupTokenRefresh() {
    messaging().onTokenRefresh(async (token) => {
      console.log('FCM Token refreshed:', token);
      if (this.adminAuthToken) {
        await this.registerToken(token);
      }
    });
  }

  // Register FCM token with backend
  async registerToken(fcmToken) {
    if (!this.adminAuthToken) {
      console.log('Admin not logged in, cannot register FCM token');
      return false;
    }

    try {
      const response = await fetch('http://your-api.com/admin/register_fcm_token', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.adminAuthToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          fcm_token: fcmToken
        })
      });

      const result = await response.json();
      
      if (result.status === 'success') {
        console.log('FCM token registered successfully');
        return true;
      } else {
        console.error('Failed to register FCM token:', result.message);
        return false;
      }
    } catch (error) {
      console.error('Error registering FCM token:', error);
      return false;
    }
  }

  // Initialize after admin login
  async initialize(adminAuthToken) {
    this.adminAuthToken = adminAuthToken;

    try {
      // Request permission (iOS)
      if (Platform.OS === 'ios') {
        const authStatus = await messaging().requestPermission();
        const enabled =
          authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
          authStatus === messaging.AuthorizationStatus.PROVISIONAL;

        if (!enabled) {
          console.log('Notification permission not granted');
          return false;
        }
      }

      // Get FCM token
      const fcmToken = await messaging().getToken();
      console.log('FCM Token:', fcmToken);

      // Register token
      return await this.registerToken(fcmToken);
    } catch (error) {
      console.error('Error initializing notifications:', error);
      return false;
    }
  }
}

// Usage
const notificationService = new AdminNotificationService();

// After admin login
async function onAdminLogin(loginResponse) {
  const adminAuthToken = loginResponse.auth_token;
  await notificationService.initialize(adminAuthToken);
}
```

### Step 4: Handle Token Refresh

FCM tokens can be refreshed by Firebase. Your app should listen for token refresh and update the token:

#### React Native

```javascript
import messaging from '@react-native-firebase/messaging';

messaging().onTokenRefresh(async (token) => {
  console.log('FCM Token refreshed:', token);
  
  // Update token in backend
  await fetch('http://your-api.com/admin/register_fcm_token', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${adminAuthToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fcm_token: token
    })
  });
});
```

## Remove FCM Token (Logout)

When admin logs out, you should remove the FCM token:

**Endpoint:** `POST /admin/remove_fcm_token`

**Request:**
```bash
curl -X POST http://localhost:3000/admin/remove_fcm_token \
  -H "Authorization: Bearer YOUR_ADMIN_AUTH_TOKEN"
```

**Response:**
```json
{
  "status": "success",
  "message": "FCM token removed successfully",
  "data": {
    "admin_id": 1,
    "admin_name": "Admin User"
  }
}
```

## Complete Integration Example

Here's a complete example for React Native:

```javascript
import React, { useEffect, useState } from 'react';
import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

function AdminApp() {
  const [adminToken, setAdminToken] = useState(null);
  const [fcmToken, setFcmToken] = useState(null);

  // Login function
  const login = async (username, password, companyId) => {
    try {
      const response = await fetch('http://your-api.com/admin/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password, company_id: companyId })
      });
      
      const result = await response.json();
      if (result.status === 'success') {
        setAdminToken(result.auth_token);
        
        // Register FCM token after login
        await registerFCMToken(result.auth_token);
        
        return result;
      }
    } catch (error) {
      console.error('Login error:', error);
    }
  };

  // Register FCM token
  const registerFCMToken = async (authToken) => {
    try {
      // Request permission (iOS)
      if (Platform.OS === 'ios') {
        const authStatus = await messaging().requestPermission();
        const enabled =
          authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
          authStatus === messaging.AuthorizationStatus.PROVISIONAL;
        
        if (!enabled) {
          console.log('Notification permission denied');
          return;
        }
      }

      // Get FCM token
      const token = await messaging().getToken();
      setFcmToken(token);
      console.log('FCM Token:', token);

      // Register with backend
      const response = await fetch('http://your-api.com/admin/register_fcm_token', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${authToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ fcm_token: token })
      });

      const result = await response.json();
      if (result.status === 'success') {
        console.log('FCM token registered successfully');
      }
    } catch (error) {
      console.error('FCM token registration error:', error);
    }
  };

  // Setup token refresh listener
  useEffect(() => {
    const unsubscribe = messaging().onTokenRefresh(async (token) => {
      console.log('FCM Token refreshed:', token);
      setFcmToken(token);
      
      if (adminToken) {
        await registerFCMToken(adminToken);
      }
    });

    return () => unsubscribe();
  }, [adminToken]);

  // Setup notification handlers
  useEffect(() => {
    // Foreground notifications
    const unsubscribeForeground = messaging().onMessage(async remoteMessage => {
      console.log('Foreground notification:', remoteMessage);
      // Show notification or update UI
    });

    // Background/quit state notifications
    messaging().setBackgroundMessageHandler(async remoteMessage => {
      console.log('Background notification:', remoteMessage);
    });

    return () => {
      unsubscribeForeground();
    };
  }, []);

  // Logout function
  const logout = async () => {
    if (adminToken) {
      // Remove FCM token
      await fetch('http://your-api.com/admin/remove_fcm_token', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${adminToken}`,
          'Content-Type': 'application/json'
        }
      });

      // Logout from API
      await fetch('http://your-api.com/admin/logout', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${adminToken}`,
          'Content-Type': 'application/json'
        }
      });
    }

    setAdminToken(null);
    setFcmToken(null);
  };

  return (
    // Your app UI here
    <View>
      {/* App content */}
    </View>
  );
}

export default AdminApp;
```

## Testing the Registration

You can test the FCM token registration using cURL or Postman:

1. **Get Admin Auth Token:**
```bash
curl -X POST http://localhost:3000/admin/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "password",
    "company_id": 1
  }'
```

2. **Register FCM Token:**
```bash
curl -X POST http://localhost:3000/admin/register_fcm_token \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN_FROM_STEP_1" \
  -H "Content-Type: application/json" \
  -d '{
    "fcm_token": "test_token_12345"
  }'
```

3. **Verify Registration:**
Check the database:
```sql
SELECT uid, name, fcm_token FROM staff WHERE user_type = 'admin' AND fcm_token IS NOT NULL;
```

## Important Notes

1. **Token Uniqueness**: Each device/app instance has a unique FCM token
2. **Token Refresh**: FCM tokens can change, so listen for refresh events
3. **Multiple Devices**: Each device where an admin logs in should register its own token
4. **Token Cleanup**: Remove tokens on logout to prevent notifications on logged-out devices
5. **Permission Required**: iOS requires notification permission before getting FCM token
6. **Token Format**: FCM tokens are long strings (typically 150+ characters)

## Troubleshooting

### Token Registration Fails

- **401 Unauthorized**: Check if admin auth token is valid and not expired
- **400 Bad Request**: Ensure `fcm_token` field is included in request body
- **500 Error**: Check server logs for database connection issues

### Token Not Received in Mobile App

- Verify Firebase is properly configured in your mobile app
- Check notification permissions (especially on iOS)
- Ensure Firebase SDK is properly installed
- Check Firebase Console for project configuration

### Notifications Not Received

- Verify FCM token is registered in database
- Check if Firebase service account is configured on server
- Verify notification payload format
- Check Firebase Console for delivery logs

## Related Endpoints

- `POST /admin/login` - Admin login (get auth token)
- `POST /admin/remove_fcm_token` - Remove FCM token (logout)
- `POST /send_notification_to_admins` - Send test notification (from agents)
- `POST /check_in` - Agent check-in (sends notification to admins)

