"use client"; import { initializeApp, getApps, type FirebaseApp } from "firebase/app"; import { getMessaging, getToken, onMessage, type Messaging, } from "firebase/messaging"; let app: FirebaseApp | null = null; let messaging: Messaging | null = null; export function initFirebase() { if (typeof window === "undefined") return; const { NEXT_PUBLIC_FIREBASE_API_KEY, NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, NEXT_PUBLIC_FIREBASE_PROJECT_ID, NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, NEXT_PUBLIC_FIREBASE_APP_ID, } = process.env; if ( !NEXT_PUBLIC_FIREBASE_API_KEY || !NEXT_PUBLIC_FIREBASE_PROJECT_ID ) { console.warn( "Firebase config not fully provided. Browser push notifications will be disabled.", ); return; } if (getApps().length === 0) { app = initializeApp({ apiKey: NEXT_PUBLIC_FIREBASE_API_KEY, authDomain: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, projectId: NEXT_PUBLIC_FIREBASE_PROJECT_ID, storageBucket: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, messagingSenderId: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, appId: NEXT_PUBLIC_FIREBASE_APP_ID, }); } else { app = getApps()[0]; } try { messaging = getMessaging(app); } catch (err) { console.warn("Failed to initialize Firebase Messaging", err); } } export function getFirebaseMessaging(): Messaging | null { return messaging; } /** * Request notification permission and retrieve the FCM registration token. * Returns the token string, or null if permission is not granted or FCM is unavailable. */ export async function registerFcmToken(): Promise { if (!messaging) { console.warn("Firebase Messaging not initialized"); return null; } try { const permission = await Notification.requestPermission(); if (permission !== "granted") { console.warn("Notification permission not granted"); return null; } const token = await getToken(messaging, { vapidKey: process.env.NEXT_PUBLIC_FIREBASE_VAPID_KEY, }); if (!token) { console.warn("Failed to retrieve FCM token"); return null; } return token; } catch (err) { console.warn("Failed to register FCM token", err); return null; } } /** * Listen for foreground messages and dispatch a custom event so the UI can react. */ export function onForegroundMessage( callback: (payload: any) => void, ): (() => void) | null { if (!messaging) return null; const unsubscribe = onMessage(messaging, (payload) => { callback(payload); }); return unsubscribe; }