const {onRequest} = require("firebase-functions/v2/https");
const {getAuth} = require("firebase-admin/auth");
const {getFirestore, Timestamp} = require("firebase-admin/firestore");
const logger = require("firebase-functions/logger");
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {Expo} = require('expo-server-sdk');

admin.initializeApp();
const db = admin.firestore();

let expo = new Expo({accessToken: process.env.EXPO_ACCESS_TOKEN});
let notificationTimeout = null;
let eventCount = 0;
let notificationInProgress = false;

const GOOGLE_CALENDAR_ID = "primary";
const CHANNEL_ID = "cally-family-calendar";
const WEBHOOK_URL = "https://us-central1-cally-family-calendar.cloudfunctions.net/sendSyncNotification";

exports.sendNotificationOnEventCreation = functions.firestore
    .document('Events/{eventId}')
    .onCreate(async (snapshot, context) => {
        const eventData = snapshot.data();
        const { familyId, creatorId, email, title } = eventData;

        if (!!eventData?.externalOrigin) {
            console.log('Externally synced event, ignoring.')
            return;
        }

        if (!familyId || !creatorId) {
            console.error('Missing familyId or creatorId in event data');
            return;
        }

        let pushTokens = await getPushTokensForFamilyExcludingCreator(familyId, creatorId);

        if (!pushTokens.length) {
            console.log('No push tokens available for the event.');
            return;
        }

        eventCount++;

        // Only set up the notification timeout if it's not already in progress
        if (!notificationInProgress) {
            notificationInProgress = true;

            notificationTimeout = setTimeout(async () => {
                const eventMessage = eventCount === 1
                    ? `An event "${title}" has been added. Check it out!`
                    : `${eventCount} new events have been added.`;

                let messages = pushTokens.map(pushToken => {
                    if (!Expo.isExpoPushToken(pushToken)) {
                        console.error(`Push token ${pushToken} is not a valid Expo push token`);
                        return null;
                    }

                    return {
                        to: pushToken,
                        sound: 'default',
                        title: 'New Events Added!',
                        body: eventMessage,
                        data: { eventId: context.params.eventId },
                    };
                }).filter(Boolean);

                let chunks = expo.chunkPushNotifications(messages);
                let tickets = [];

                for (let chunk of chunks) {
                    try {
                        let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
                        tickets.push(...ticketChunk);

                        for (let ticket of ticketChunk) {
                            if (ticket.status === 'ok') {
                                console.log('Notification successfully sent:', ticket.id);
                            } else if (ticket.status === 'error') {
                                console.error(`Notification error: ${ticket.message}`);
                                if (ticket.details?.error === 'DeviceNotRegistered') {
                                    await removeInvalidPushToken(ticket.to);
                                }
                            }
                        }
                    } catch (error) {
                        console.error('Error sending notification:', error);
                    }
                }

                // Save the notification in Firestore for record-keeping
                const notificationData = {
                    creatorId,
                    familyId,
                    content: eventMessage,
                    eventId: context.params.eventId,
                    timestamp: Timestamp.now(),
                };

                try {
                    await db.collection("Notifications").add(notificationData);
                    console.log("Notification stored in Firestore:", notificationData);
                } catch (error) {
                    console.error("Error saving notification to Firestore:", error);
                }

                // Reset state variables after notifications are sent
                eventCount = 0;
                pushTokens = [];
                notificationInProgress = false;

            }, 5000);
        }
    });

exports.createSubUser = onRequest(async (request, response) => {
    const authHeader = request.get('Authorization');

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        logger.warn("Missing or incorrect Authorization header", {authHeader});
        response.status(401).json({error: 'Unauthorized'});
        return;
    }

    try {
        const token = authHeader.split('Bearer ')[1];
        logger.info("Verifying ID token", {token});

        let decodedToken;
        try {
            decodedToken = await getAuth().verifyIdToken(token);
            logger.info("ID token verified successfully", {uid: decodedToken.uid});
        } catch (verifyError) {
            logger.error("ID token verification failed", {error: verifyError.message});
            response.status(401).json({error: 'Unauthorized: Invalid token'});
            return;
        }

        logger.info("Processing user creation", {requestBody: request.body.data});

        const {userType, firstName, lastName, email, password, familyId} = request.body.data;

        if (!email || !password || !firstName || !userType || !familyId) {
            logger.warn("Missing required fields in request body", {requestBody: request.body.data});
            response.status(400).json({error: "Missing required fields"});
            return;
        }

        let userRecord;
        try {
            userRecord = await getAuth().createUser({
                email, password, displayName: `${firstName} ${lastName}`,
            });
            logger.info("User record created", {userId: userRecord.uid});
        } catch (createUserError) {
            logger.error("User creation failed", {error: createUserError.message});
            response.status(500).json({error: "Failed to create user"});
            return;
        }

        const userProfile = {
            userType, firstName, lastName, familyId, email, uid: userRecord.uid
        };

        try {
            await getFirestore().collection("Profiles").doc(userRecord.uid).set(userProfile);
            logger.info("User profile saved to Firestore", {userId: userRecord.uid});
        } catch (firestoreError) {
            logger.error("Failed to save user profile to Firestore", {error: firestoreError.message});
            response.status(500).json({error: "Failed to save user profile"});
            return;
        }

        response.status(200).json({
            data: {
                message: "User created successfully", userId: userRecord.uid,
            }
        });
    } catch (error) {
        logger.error("Error in createSubUser function", {error: error.message});
        response.status(500).json({data: {error: error.message}});
    }
});

exports.removeSubUser = onRequest(async (request, response) => {
    const authHeader = request.get('Authorization');

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        logger.warn("Missing or incorrect Authorization header", {authHeader});
        response.status(401).json({error: 'Unauthorized'});
        return;
    }

    try {
        const token = authHeader.split('Bearer ')[1];
        logger.info("Verifying ID token", {token});

        let decodedToken;
        try {
            decodedToken = await getAuth().verifyIdToken(token);
            logger.info("ID token verified successfully", {uid: decodedToken.uid});
        } catch (verifyError) {
            logger.error("ID token verification failed", {error: verifyError.message});
            response.status(401).json({error: 'Unauthorized: Invalid token'});
            return;
        }

        logger.info("Processing user removal", {requestBody: request.body.data});

        const { userId, familyId } = request.body.data;

        if (!userId || !familyId) {
            logger.warn("Missing required fields in request body", {requestBody: request.body.data});
            response.status(400).json({error: "Missing required fields"});
            return;
        }

        try {
            const userProfile = await getFirestore()
                .collection("Profiles")
                .doc(userId)
                .get();

            if (!userProfile.exists) {
                logger.error("User profile not found", {userId});
                response.status(404).json({error: "User not found"});
                return;
            }

            if (userProfile.data().familyId !== familyId) {
                logger.error("User does not belong to the specified family", {
                    userId,
                    requestedFamilyId: familyId,
                    actualFamilyId: userProfile.data().familyId
                });
                response.status(403).json({error: "User does not belong to the specified family"});
                return;
            }

            await getFirestore()
                .collection("Profiles")
                .doc(userId)
                .delete();
            logger.info("User profile deleted from Firestore", {userId});

            await getAuth().deleteUser(userId);
            logger.info("User authentication deleted", {userId});

            response.status(200).json({
                data: {
                    message: "User removed successfully",
                    success: true
                }
            });
        } catch (error) {
            logger.error("Failed to remove user", {error: error.message});
            response.status(500).json({error: "Failed to remove user"});
            return;
        }
    } catch (error) {
        logger.error("Error in removeSubUser function", {error: error.message});
        response.status(500).json({data: {error: error.message}});
    }
});

exports.generateCustomToken = onRequest(async (request, response) => {
    try {
        const {userId} = request.body.data;

        console.log("Generating custom token for userId", {userId});

        if (!userId) {
            response.status(400).json({error: 'Missing userId'});
            return;
        }

        const customToken = await getAuth().createCustomToken(userId);
        response.status(200).json({data: {token: customToken}});
    } catch (error) {
        console.error("Error generating custom token", {error: error.message});
        response.status(500).json({error: "Failed to generate custom token"});
    }
});

exports.refreshTokens = functions.pubsub.schedule('every 45 minutes').onRun(async (context) => {
    console.log('Running token refresh job...');

    const profilesSnapshot = await db.collection('Profiles').get();

    profilesSnapshot.forEach(async (profileDoc) => {
        const profileData = profileDoc.data();

        if (profileData.googleAccounts) {
            try {
                for (const googleEmail of Object.keys(profileData?.googleAccounts)) {
                    const googleToken = profileData?.googleAccounts?.[googleEmail]?.refreshToken;
                    if (googleToken) {
                        const {refreshedGoogleToken, refreshedRefreshToken} = await refreshGoogleToken(googleToken);
                        const updatedGoogleAccounts = {
                            ...profileData.googleAccounts,
                            [googleEmail]: {accessToken: refreshedGoogleToken, refreshToken: refreshedRefreshToken}
                        };
                        await profileDoc.ref.update({googleAccounts: updatedGoogleAccounts});
                        console.log(`Google token updated for user ${profileDoc.id}`);
                    }
                }
            } catch (error) {
                console.error(`Error refreshing Google token for user ${profileDoc.id}:`, error.message);
            }
        }

        if (profileData.microsoftAccounts) {
            try {
                for (const microsoftEmail of Object.keys(profileData?.microsoftAccounts)) {
                    const microsoftToken = profileData?.microsoftAccounts?.[microsoftEmail];
                    if (microsoftToken) {
                        const refreshedMicrosoftToken = await refreshMicrosoftToken(microsoftToken);
                        const updatedMicrosoftAccounts = {
                            ...profileData.microsoftAccounts,
                            [microsoftEmail]: refreshedMicrosoftToken
                        };
                        await profileDoc.ref.update({microsoftAccounts: updatedMicrosoftAccounts});
                        console.log(`Microsoft token updated for user ${profileDoc.id}`);
                    }
                }
            } catch (error) {
                console.error(`Error refreshing Microsoft token for user ${profileDoc.id}:`, error.message);
            }
        }

        if (profileData.appleAccounts) {
            try {
                for (const appleEmail of Object.keys(profileData?.appleAccounts)) {
                    const appleToken = profileData?.appleAccounts?.[appleEmail];
                    const refreshedAppleToken = await refreshAppleToken(appleToken);
                    const updatedAppleAccounts = {...profileData.appleAccounts, [appleEmail]: refreshedAppleToken};
                    await profileDoc.ref.update({appleAccunts: updatedAppleAccounts});
                    console.log(`Apple token updated for user ${profileDoc.id}`);
                }
            } catch (error) {
                console.error(`Error refreshing Apple token for user ${profileDoc.id}:`, error.message);
            }
        }
    });

    return null;
});

async function refreshMicrosoftToken(refreshToken) {
    try {
        const response = await axios.post('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
            grant_type: 'refresh_token',
            refresh_token: refreshToken,
            client_id: "13c79071-1066-40a9-9f71-b8c4b138b4af", // Client ID from microsoftConfig
            scope: "openid profile email offline_access Calendars.ReadWrite User.Read", // Scope from microsoftConfig
        });

        return response.data.access_token; // Return the new access token
    } catch (error) {
        console.error("Error refreshing Microsoft token:", error);
        throw error;
    }
}

async function getPushTokensForEvent() {
    const usersRef = db.collection('Profiles');
    const snapshot = await usersRef.get();
    let pushTokens = [];

    snapshot.forEach(doc => {
        const data = doc.data();
        if (data.pushToken) {
            pushTokens.push(data.pushToken);
        }
    });

    console.log('Push Tokens:', pushTokens);
    return pushTokens;
}

async function getPushTokensForFamilyExcludingCreator(familyId, creatorId) {
    const usersRef = db.collection('Profiles');
    const snapshot = await usersRef.where('familyId', '==', familyId).get();
    let pushTokens = [];

    snapshot.forEach(doc => {
        const data = doc.data();
        // Exclude the creator
        if (data.uid !== creatorId && data.pushToken) {
            pushTokens.push(data.pushToken);
        }
    });

    return pushTokens;
}

async function removeInvalidPushToken(pushToken) {
    // TODO
}

const fetch = require("node-fetch");

// Function to refresh Google Token with additional logging
async function refreshGoogleToken(refreshToken) {
    try {
        console.log("Refreshing Google token...");
        const response = await fetch("https://oauth2.googleapis.com/token", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                grant_type: "refresh_token",
                refresh_token: refreshToken,
                client_id: "406146460310-2u67ab2nbhu23trp8auho1fq4om29fc0.apps.googleusercontent.com",
            }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            console.error("Error refreshing Google token:", errorData);
            throw new Error(`Failed to refresh Google token: ${errorData.error || response.statusText}`);
        }

        const data = await response.json();
        console.log("Google token refreshed successfully");

        // Return both the access token and refresh token (if a new one is provided)
        return {
            refreshedGoogleToken: data.access_token,
            refreshedRefreshToken: data.refresh_token || refreshToken, // Return the existing refresh token if a new one is not provided
        };
    } catch (error) {
        console.error("Error refreshing Google token:", error.message);
        throw error;
    }
}

// Helper function to get Google access tokens for all users and refresh them if needed with logging
async function getGoogleAccessTokens() {
    console.log("Fetching Google access tokens for all users...");
    const tokens = {};
    const profilesSnapshot = await db.collection("Profiles").get();

    await Promise.all(
        profilesSnapshot.docs.map(async (doc) => {
            const profileData = doc.data();
            const googleAccounts = profileData?.googleAccounts || {};

            for (const googleEmail of Object.keys(googleAccounts)) {
                // Check if the googleAccount entry exists and has a refreshToken
                const accountInfo = googleAccounts[googleEmail];
                const refreshToken = accountInfo?.refreshToken;

                if (refreshToken) {
                    try {
                        console.log(`Refreshing token for user ${doc.id} (email: ${googleEmail})`);
                        const {refreshedGoogleToken} = await refreshGoogleToken(refreshToken);
                        tokens[doc.id] = accessToken;
                        console.log(`Token refreshed successfully for user ${doc.id}`);
                    } catch (error) {
                        tokens[doc.id] = accountInfo?.accessToken;
                        console.error(`Failed to refresh token for user ${doc.id}:`, error.message);
                    }
                } else {
                    console.log(`No refresh token available for user ${doc.id} (email: ${googleEmail})`);
                }
            }
        })
    );

    console.log("Access tokens fetched and refreshed as needed");
    return tokens;
}

// Function to watch Google Calendar events with additional logging
const watchCalendarEvents = async (userId, token) => {
    const url = `https://www.googleapis.com/calendar/v3/calendars/${GOOGLE_CALENDAR_ID}/events/watch`;

    // Verify the token is valid
    console.log(`Attempting to watch calendar for user ${userId}`);
    console.log(`Token being used: ${token ? 'present' : 'missing'}`);
    console.log(`Calendar ID: ${GOOGLE_CALENDAR_ID}`);
    console.log(`Webhook URL: ${WEBHOOK_URL}?userId=${userId}`);

    try {
        // Test the token first
        const testResponse = await fetch(
            `https://www.googleapis.com/calendar/v3/calendars/${GOOGLE_CALENDAR_ID}/events?maxResults=1`,
            {
                headers: {
                    Authorization: `Bearer ${token}`,
                },
            }
        );

        if (!testResponse.ok) {
            console.error(`Token validation failed for user ${userId}:`, await testResponse.text());
            throw new Error('Token validation failed');
        }

        console.log(`Token validated successfully for user ${userId}`);

        const response = await fetch(url, {
            method: "POST",
            headers: {
                Authorization: `Bearer ${token}`,
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                id: `${CHANNEL_ID}-${userId}`,
                type: "web_hook",
                address: `${WEBHOOK_URL}?userId=${userId}`,
                params: {
                    ttl: "80000",
                },
            }),
        });

        const responseText = await response.text();
        console.log(`Watch response for user ${userId}:`, responseText);

        if (!response.ok) {
            console.error(`Failed to watch calendar for user ${userId}:`, responseText);
            throw new Error(`Failed to watch calendar: ${responseText}`);
        }

        const result = JSON.parse(responseText);
        console.log(`Successfully set up Google Calendar watch for user ${userId}`, result);

        // Store the watch details in Firestore for monitoring
        await db.collection('CalendarWatches').doc(userId).set({
            watchId: result.id,
            resourceId: result.resourceId,
            expiration: result.expiration,
            createdAt: admin.firestore.FieldValue.serverTimestamp(),
        });

        return result;
    } catch (error) {
        console.error(`Error in watchCalendarEvents for user ${userId}:`, error);
        // Store the error in Firestore for monitoring
        await db.collection('CalendarWatchErrors').add({
            userId,
            error: error.message,
            timestamp: admin.firestore.FieldValue.serverTimestamp(),
        });
        throw error;
    }
};

// Add this to test webhook connectivity
exports.testWebhook = functions.https.onRequest(async (req, res) => {
    console.log('Test webhook received');
    console.log('Headers:', req.headers);
    console.log('Body:', req.body);
    console.log('Query:', req.query);

    res.status(200).send('Test webhook received successfully');
});

// Schedule function to renew Google Calendar watch every 20 hours for each user with logging
exports.renewGoogleCalendarWatch = functions.pubsub.schedule("every 10 minutes").onRun(async (context) => {
    console.log("Starting Google Calendar watch renewal process...");
    try {
        const tokens = await getGoogleAccessTokens();
        console.log("Tokens: ", tokens);

        for (const [userId, token] of Object.entries(tokens)) {
            try {
                await watchCalendarEvents(userId, token);
            } catch (error) {
                console.error(`Error renewing Google Calendar watch for user ${userId}:`, error.message);
            }
        }

        console.log("Google Calendar watch renewal process completed");
    } catch (error) {
        console.error("Error in renewGoogleCalendarWatch function:", error.message);
    }
});

// Function to handle notifications from Google Calendar with additional logging
exports.sendSyncNotification = functions.https.onRequest(async (req, res) => {
    const userId = req.query.userId; // Extract userId from query params
    const calendarId = req.body.resourceId;

    console.log(`Received notification for user ${userId} with calendar ID ${calendarId}`);

    try {
        // Fetch user profile data for the specific user
        const userDoc = await db.collection("Profiles").doc(userId).get();
        const userData = userDoc.data();

        // Ensure pushTokens is an array
        let pushTokens = [];
        if (userData && userData.pushToken) {
            pushTokens = Array.isArray(userData.pushToken) ? userData.pushToken : [userData.pushToken];
        }

        if (pushTokens.length === 0) {
            console.log(`No push tokens found for user ${userId}`);
            res.status(200).send("No push tokens found for user.");
            return;
        }

        // Call calendarSync with necessary parameters
        const {googleAccounts} = userData;
        const email = Object.keys(googleAccounts || {})[0]; // Assuming the first account is the primary
        const accountData = googleAccounts[email] || {};
        const token = accountData.accessToken;
        const refreshToken = accountData.refreshToken;
        const familyId = userData.familyId;

        console.log("Starting calendar sync...");
        await calendarSync({userId, email, token, refreshToken, familyId});
        console.log("Calendar sync completed.");

        // Prepare and send push notifications after sync
        // const syncMessage = "New events have been synced.";
        //
        // let messages = pushTokens.map(pushToken => {
        //     if (!Expo.isExpoPushToken(pushToken)) {
        //         console.error(`Push token ${pushToken} is not a valid Expo push token`);
        //         return null;
        //     }
        //
        //     return {
        //         to: pushToken,
        //         sound: "default",
        //         title: "Event Sync",
        //         body: syncMessage,
        //         data: { userId, calendarId },
        //     };
        // }).filter(Boolean);
        //
        // let chunks = expo.chunkPushNotifications(messages);
        // let tickets = [];
        //
        // for (let chunk of chunks) {
        //     try {
        //         let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
        //         tickets.push(...ticketChunk);
        //
        //         for (let ticket of ticketChunk) {
        //             if (ticket.status === "ok") {
        //                 console.log("Notification successfully sent:", ticket.id);
        //             } else if (ticket.status === "error") {
        //                 console.error(`Notification error: ${ticket.message}`);
        //                 if (ticket.details?.error === "DeviceNotRegistered") {
        //                     await removeInvalidPushToken(ticket.to);
        //                 }
        //             }
        //         }
        //     } catch (error) {
        //         console.error("Error sending notification:", error.message);
        //     }
        // }
        //
        // console.log(`Sync notification sent for user ${userId}`);
        res.status(200).send("Sync notification sent.");
    } catch (error) {
        console.error(`Error in sendSyncNotification for user ${userId}:`, error.message);
        res.status(500).send("Failed to send sync notification.");
    }
});

async function fetchAndSaveGoogleEvents({ token, refreshToken, email, familyId, creatorId }) {
    const baseDate = new Date();
    const timeMin = new Date(baseDate.setMonth(baseDate.getMonth() - 1)).toISOString();
    const timeMax = new Date(baseDate.setMonth(baseDate.getMonth() + 2)).toISOString();

    let events = [];
    let pageToken = null;

    try {
        console.log(`Fetching events for user: ${email}`);

        // Fetch all events from Google Calendar within the specified time range
        do {
            const url = new URL(`https://www.googleapis.com/calendar/v3/calendars/primary/events`);
            url.searchParams.set("singleEvents", "true");
            url.searchParams.set("timeMin", timeMin);
            url.searchParams.set("timeMax", timeMax);
            if (pageToken) url.searchParams.set("pageToken", pageToken);

            const response = await fetch(url.toString(), {
                headers: {
                    Authorization: `Bearer ${token}`,
                },
            });

            const data = await response.json();

            if (response.status === 401 && refreshToken) {
                console.log(`Token expired for user: ${email}, attempting to refresh`);
                const refreshedToken = await refreshGoogleToken(refreshToken);
                token = refreshedToken;

                if (token) {
                    return fetchAndSaveGoogleEvents({ token, refreshToken, email, familyId, creatorId });
                } else {
                    console.error(`Failed to refresh token for user: ${email}`);
                    await clearToken(email);
                    return;
                }
            }

            if (!response.ok) {
                throw new Error(`Error fetching events: ${data.error?.message || response.statusText}`);
            }

            console.log(`Processing events for user: ${email}`);
            data.items?.forEach((item) => {
                const googleEvent = {
                    id: item.id,
                    title: item.summary || "",
                    startDate: item.start?.dateTime ? new Date(item.start.dateTime) : new Date(item.start.date),
                    endDate: item.end?.dateTime ? new Date(item.end.dateTime) : new Date(item.end.date),
                    allDay: !item.start?.dateTime,
                    familyId,
                    email,
                    creatorId,
                    externalOrigin: "google",
                };
                events.push(googleEvent);
                console.log(`Processed event: ${JSON.stringify(googleEvent)}`);
            });

            pageToken = data.nextPageToken;
        } while (pageToken);

        console.log(`Saving events to Firestore for user: ${email}`);
        await saveEventsToFirestore(events);
    } catch (error) {
        console.error(`Error fetching Google Calendar events for ${email}:`, error);
    }
}

async function saveEventsToFirestore(events) {
    const batch = db.batch();
    events.forEach((event) => {
        const eventRef = db.collection("Events").doc(event.id);
        batch.set(eventRef, event, { merge: true });
    });
    await batch.commit();
}

async function calendarSync({ userId, email, token, refreshToken, familyId }) {
    console.log(`Starting calendar sync for user ${userId} with email ${email}`);
    try {
        await fetchAndSaveGoogleEvents({
            token,
            refreshToken,
            email,
            familyId,
            creatorId: userId,
        });
        console.log("Calendar events synced successfully.");
    } catch (error) {
        console.error(`Error syncing calendar for user ${userId}:`, error);
        throw error;
    }
    console.log(`Finished calendar sync for user ${userId}`);
}

exports.sendSyncNotification = functions.https.onRequest(async (req, res) => {
    const userId = req.query.userId;
    const calendarId = req.body.resourceId;

    console.log(`Received notification for user ${userId} with calendar ID ${calendarId}`);

    try {
        const userDoc = await db.collection("Profiles").doc(userId).get();
        const userData = userDoc.data();

        let pushTokens = [];
        if (userData && userData.pushToken) {
            pushTokens = Array.isArray(userData.pushToken) ? userData.pushToken : [userData.pushToken];
        }

        if (pushTokens.length === 0) {
            console.log(`No push tokens found for user ${userId}`);
            res.status(200).send("No push tokens found for user.");
            return;
        }

        const { googleAccounts } = userData;
        const email = Object.keys(googleAccounts || {})[0];
        const accountData = googleAccounts[email] || {};
        const token = accountData.accessToken;
        const refreshToken = accountData.refreshToken;
        const familyId = userData.familyId;

        console.log("Starting calendar sync...");
        await calendarSync({ userId, email, token, refreshToken, familyId });
        console.log("Calendar sync completed.");

        res.status(200).send("Sync notification sent.");
    } catch (error) {
        console.error(`Error in sendSyncNotification for user ${userId}:`, error.message);
        res.status(500).send("Failed to send sync notification.");
    }
});