# Firebase Cloud Messaging Setup Guide

This comprehensive guide walks you through setting up Firebase Cloud Messaging (FCM) for both Android and iOS platforms with the Milton Health Coach FCM Client SDK.

## Prerequisites

- React Native 0.60.0 or higher
- Node.js 14 or higher
- Xcode 12+ (for iOS development)
- Android Studio 4.0+ (for Android development)
- Firebase account

## Step 1: Create Firebase Project

### 1.1 Create New Project

1. Go to [Firebase Console](https://console.firebase.google.com/)
2. Click **"Create a project"** or **"Add project"**
3. Enter your project name (e.g., "Milton Health Coach")
4. Choose whether to enable Google Analytics (recommended)
5. Select or create a Google Analytics account
6. Click **"Create project"**

### 1.2 Project Settings

1. In Firebase Console, click the gear icon → **"Project settings"**
2. Note your **Project ID** - you'll need this later
3. Go to **"Cloud Messaging"** tab
4. Note your **Server key** - this will be used by your backend

## Step 2: Add Android App

### 2.1 Register Android App

1. In Firebase Console, click **"Add app"** → Android icon
2. **Android package name**: Found in `android/app/build.gradle`
   ```gradle
   android {
       defaultConfig {
           applicationId "com.yourcompany.yourapp" // This is your package name
       }
   }
   ```
3. **App nickname**: Optional (e.g., "Milton Android")
4. **Debug signing certificate SHA-1**: 
   - For development, get it by running:
   ```bash
   cd android
   ./gradlew signingReport
   ```
   - Look for the SHA1 under "Variant: debug"
   - Copy the SHA1 hash (format: `AA:BB:CC:...`)

### 2.2 Download Configuration File

1. Click **"Download google-services.json"**
2. Place the file in `android/app/google-services.json`
3. **Important**: Ensure the file is exactly in `android/app/` directory

### 2.3 Add Firebase SDK

1. **Project-level** `android/build.gradle`:
   ```gradle
   buildscript {
       dependencies {
           // ... existing dependencies
           classpath 'com.google.gms:google-services:4.3.15'
       }
   }
   ```

2. **App-level** `android/app/build.gradle`:
   ```gradle
   apply plugin: 'com.android.application'
   apply plugin: 'com.google.gms.google-services' // Add this line
   
   dependencies {
       implementation 'com.google.firebase:firebase-messaging:23.1.2'
       // ... other dependencies
   }
   ```

### 2.4 Update Android Manifest

Edit `android/app/src/main/AndroidManifest.xml`:

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- Required permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
    <application
        android:name=".MainApplication"
        android:allowBackup="false"
        android:theme="@style/AppTheme">
        
        <!-- ... existing configuration ... -->
        
        <!-- Firebase Messaging Service -->
        <service
            android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        
        <!-- Optional: Custom notification icon -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/ic_notification" />
            
        <!-- Optional: Custom notification color -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/notification_color" />
            
        <!-- Optional: Default notification channel -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="milton_notifications" />
            
    </application>
</manifest>
```

### 2.5 Create Notification Icons (Optional)

1. Create notification icons in `android/app/src/main/res/drawable/`:
   - `ic_notification.xml` or `ic_notification.png`
   - Use white icons with transparent background
   - Recommended sizes: 24x24dp

2. Define notification color in `android/app/src/main/res/values/colors.xml`:
   ```xml
   <?xml version="1.0" encoding="utf-8"?>
   <resources>
       <color name="notification_color">#2196F3</color>
   </resources>
   ```

## Step 3: Add iOS App

### 3.1 Register iOS App

1. In Firebase Console, click **"Add app"** → iOS icon
2. **iOS bundle ID**: Found in Xcode project settings
   - Open `ios/YourApp.xcworkspace` in Xcode
   - Select your project → Target → General tab
   - Copy the **Bundle Identifier**
3. **App nickname**: Optional (e.g., "Milton iOS")
4. **App Store ID**: Optional (leave blank for development)

### 3.2 Download Configuration File

1. Click **"Download GoogleService-Info.plist"**
2. **Important**: Add the file to your Xcode project:
   - Open Xcode
   - Right-click your project in navigator
   - Choose **"Add Files to [ProjectName]"**
   - Select the downloaded `GoogleService-Info.plist`
   - **Ensure "Add to target" is checked** for your main app target
   - **Ensure "Copy items if needed" is checked**

### 3.3 Configure iOS Project

1. **Update Podfile** (`ios/Podfile`):
   ```ruby
   platform :ios, '11.0'
   require_relative '../node_modules/react-native/scripts/react_native_pods'
   require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
   
   target 'YourAppName' do
     config = use_native_modules!
     
     use_react_native!(
       :path => config[:reactNativePath],
       :hermes_enabled => true
     )
     
     # Firebase pods are automatically added by @react-native-firebase/app
     
     post_install do |installer|
       react_native_post_install(installer)
     end
   end
   ```

2. **Install pods**:
   ```bash
   cd ios
   pod install
   ```

### 3.4 Enable Push Notifications in Xcode

1. Open `ios/YourApp.xcworkspace` in Xcode
2. Select your project in navigator
3. Select your target
4. Go to **"Signing & Capabilities"** tab
5. Click **"+ Capability"**
6. Add **"Push Notifications"**
7. Add **"Background Modes"** and enable:
   - ✅ **Background processing**
   - ✅ **Remote notifications**

### 3.5 Update AppDelegate

Edit `ios/YourApp/AppDelegate.m`:

```objc
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Initialize Firebase
  [FIRApp configure];
  
  // ... rest of your existing code
  
  return YES;
}

// Handle APNs registration
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  NSLog(@"APNs device token: %@", deviceToken);
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  NSLog(@"Failed to register for remote notifications: %@", error);
}

// Handle notification when app is in foreground
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
  // Show notification even when app is in foreground
  completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
}

@end
```

### 3.6 Configure APNs (Apple Push Notification service)

1. **Generate APNs Key** (Recommended method):
   - Go to [Apple Developer Console](https://developer.apple.com/account/resources/authkeys/list)
   - Click **"+"** to create a new key
   - Enter key name (e.g., "Milton FCM Key")
   - Check **"Apple Push Notifications service (APNs)"**
   - Click **"Continue"** → **"Register"**
   - **Download the .p8 file** (you can only download once!)
   - Note the **Key ID**

2. **Upload APNs Key to Firebase**:
   - In Firebase Console → Project Settings → Cloud Messaging
   - Under **"Apple app configuration"**
   - Click **"Upload"** next to APNs Authentication Key
   - Upload your .p8 file
   - Enter your **Key ID** and **Team ID** (found in Apple Developer account)

## Step 4: Install React Native Firebase

### 4.1 Install Dependencies

```bash
npm install @react-native-firebase/app @react-native-firebase/messaging
```

### 4.2 Install Additional Dependencies

```bash
npm install @react-native-async-storage/async-storage @react-native-community/netinfo
```

### 4.3 iOS Pod Installation

```bash
cd ios && pod install && cd ..
```

## Step 5: Test Firebase Setup

### 5.1 Create Test Component

Create `src/components/FirebaseTest.js`:

```javascript
import React, { useEffect, useState } from 'react';
import { View, Text, Alert, StyleSheet, TouchableOpacity } from 'react-native';
import messaging from '@react-native-firebase/messaging';

const FirebaseTest = () => {
  const [fcmToken, setFcmToken] = useState(null);
  const [permissionStatus, setPermissionStatus] = useState(null);

  useEffect(() => {
    testFirebaseSetup();
    setupMessageListener();
  }, []);

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

      setPermissionStatus(enabled ? 'Granted' : 'Denied');

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

    } catch (error) {
      console.error('Firebase test failed:', error);
      Alert.alert('Firebase Error', error.message);
    }
  };

  const setupMessageListener = () => {
    // Listen for foreground messages
    const unsubscribe = messaging().onMessage(async remoteMessage => {
      console.log('FCM Message received in foreground:', remoteMessage);
      Alert.alert(
        'New Message',
        remoteMessage.notification?.body || 'You have a new message'
      );
    });

    return unsubscribe;
  };

  const sendTestNotification = () => {
    Alert.alert(
      'Test Notification',
      'To test push notifications:\n\n' +
      '1. Copy your FCM token (shown below)\n' +
      '2. Go to Firebase Console → Cloud Messaging\n' +
      '3. Click "Send your first message"\n' +
      '4. Enter a title and message\n' +
      '5. Click "Send test message"\n' +
      '6. Paste your FCM token\n' +
      '7. Click "Test"'
    );
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Firebase Setup Test</Text>
      
      <View style={styles.statusContainer}>
        <Text style={styles.label}>Permission Status:</Text>
        <Text style={[
          styles.status,
          { color: permissionStatus === 'Granted' ? '#4CAF50' : '#F44336' }
        ]}>
          {permissionStatus || 'Checking...'}
        </Text>
      </View>

      <View style={styles.tokenContainer}>
        <Text style={styles.label}>FCM Token:</Text>
        <Text style={styles.token} selectable>
          {fcmToken || 'Generating...'}
        </Text>
      </View>

      <TouchableOpacity style={styles.button} onPress={sendTestNotification}>
        <Text style={styles.buttonText}>How to Test Notifications</Text>
      </TouchableOpacity>

      <TouchableOpacity style={styles.button} onPress={testFirebaseSetup}>
        <Text style={styles.buttonText}>Refresh Test</Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 30,
  },
  statusContainer: {
    marginBottom: 20,
  },
  label: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 8,
  },
  status: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  tokenContainer: {
    marginBottom: 30,
  },
  token: {
    fontSize: 10,
    fontFamily: 'monospace',
    backgroundColor: 'white',
    padding: 12,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#ddd',
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
    marginBottom: 12,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: '600',
  },
});

export default FirebaseTest;
```

### 5.2 Test with Firebase Console

1. Go to Firebase Console → Cloud Messaging
2. Click **"Send your first message"**
3. Enter test title and message
4. Click **"Send test message"**
5. Paste your FCM token from the test component
6. Click **"Test"**

## Step 6: Production Configuration

### 6.1 Android Production Setup

1. **Generate signed APK key**:
   ```bash
   cd android/app
   keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
   ```

2. **Get production SHA-1**:
   ```bash
   keytool -list -v -keystore my-release-key.keystore -alias my-key-alias
   ```

3. **Add production SHA-1 to Firebase**:
   - Firebase Console → Project Settings → Your Android App
   - Add the production SHA-1 fingerprint

### 6.2 iOS Production Setup

1. **Create Production APNs Certificate** (Alternative to APNs Key):
   - Apple Developer Console → Certificates
   - Create new certificate → Apple Push Notification service SSL
   - Upload to Firebase Console

2. **Configure App Store Connect**:
   - Ensure push notifications capability is enabled
   - Test with TestFlight before production release

### 6.3 Environment Configuration

Create environment-specific Firebase configurations:

```javascript
// src/config/firebase.js
const firebaseConfig = {
  development: {
    // Development Firebase project config
  },
  production: {
    // Production Firebase project config
  }
};

export default firebaseConfig[__DEV__ ? 'development' : 'production'];
```

## Troubleshooting

### Common Android Issues

**google-services.json not found:**
- Ensure file is in `android/app/google-services.json`
- Clean and rebuild: `cd android && ./gradlew clean && cd ..`

**Build errors:**
- Check Google Services plugin is applied in `android/app/build.gradle`
- Ensure Firebase SDK versions are compatible
- Try: `npx react-native run-android --reset-cache`

**Notifications not received:**
- Check app is not in battery optimization whitelist
- Verify notification permissions are granted
- Test with Firebase Console test message

### Common iOS Issues

**GoogleService-Info.plist not found:**
- Ensure file is added to Xcode project (not just file system)
- Check file is included in target membership
- Clean build folder in Xcode

**APNs registration failed:**
- Verify push notifications capability is enabled
- Check provisioning profile includes push notifications
- Ensure APNs key/certificate is uploaded to Firebase

**Background notifications not working:**
- Enable "Remote notifications" in Background Modes
- Implement proper notification handling in AppDelegate
- Test with device (not simulator)

### Debug Commands

```bash
# Check React Native setup
npx react-native doctor

# Clean everything
npx react-native clean
cd android && ./gradlew clean && cd ..
cd ios && rm -rf build && pod install && cd ..

# Reset Metro cache
npx react-native start --reset-cache

# Check Firebase setup
npx @react-native-firebase/app:android:generate-json
npx @react-native-firebase/app:ios:generate-plist
```

## Security Best Practices

1. **Protect Server Key**: Never expose Firebase server key in client code
2. **Validate Tokens**: Always validate FCM tokens on your backend
3. **Secure Payload**: Don't send sensitive data in notification payload
4. **Token Refresh**: Handle token refresh events properly
5. **Certificate Management**: Rotate APNs certificates/keys regularly

## Next Steps

1. Integrate with Milton Health Coach SDK
2. Set up backend FCM integration
3. Implement notification handling in your app
4. Test thoroughly on both platforms
5. Monitor notification delivery rates

For more help, see:
- [React Native Firebase Documentation](https://rnfirebase.io/)
- [Firebase Cloud Messaging Documentation](https://firebase.google.com/docs/cloud-messaging)
- [Milton SDK Documentation](README.md)