import { useState, useEffect, useCallback } from "react"; import { useAuthContext } from "@/contexts/AuthContext"; import { useAtomValue } from "jotai"; import { useFetchAndSaveGoogleEvents } from "./useFetchAndSaveGoogleEvents"; import { useFetchAndSaveAppleEvents } from "./useFetchAndSaveAppleEvents"; import { useFetchAndSaveOutlookEvents } from "./useFetchAndSaveOutlookEvents"; import { selectedDateAtom } from "@/components/pages/calendar/atoms"; import { addDays, subDays, isBefore, isAfter, format } from "date-fns"; export const useSyncEvents = () => { const { profileData } = useAuthContext(); const selectedDate = useAtomValue(selectedDateAtom); const [lastSyncDate, setLastSyncDate] = useState(selectedDate); const [lowerBoundDate, setLowerBoundDate] = useState(subDays(selectedDate, 6 * 30)); const [upperBoundDate, setUpperBoundDate] = useState(addDays(selectedDate, 6 * 30)); const [isSyncing, setIsSyncing] = useState(false); const [error, setError] = useState(null); const syncedRanges = useState>(new Set())[0]; const { mutateAsync: fetchAndSaveGoogleEvents } = useFetchAndSaveGoogleEvents(); const { mutateAsync: fetchAndSaveOutlookEvents } = useFetchAndSaveOutlookEvents(); const { mutateAsync: fetchAndSaveAppleEvents } = useFetchAndSaveAppleEvents(); const generateRangeKey = (startDate: Date, endDate: Date) => { return `${format(startDate, "yyyy-MM-dd")}_${format(endDate, "yyyy-MM-dd")}`; }; const syncEvents = useCallback(async () => { setIsSyncing(true); setError(null); const newLowerBound = subDays(selectedDate, 6 * 30); const newUpperBound = addDays(selectedDate, 6 * 30); const rangeKey = generateRangeKey(newLowerBound, newUpperBound); if (syncedRanges.has(rangeKey)) { setIsSyncing(false); return; } if (isBefore(selectedDate, lowerBoundDate) || isAfter(selectedDate, upperBoundDate)) { try { const googleEvents = Object.entries(profileData?.googleAccounts || {}).map(([email, { accessToken }]) => fetchAndSaveGoogleEvents({ token: accessToken, email, date: selectedDate }) ); const outlookEvents = Object.entries(profileData?.microsoftAccounts || {}).map(([email, token]) => fetchAndSaveOutlookEvents({ token, email, date: selectedDate }) ); const appleEvents = Object.entries(profileData?.appleAccounts || {}).map(([email, token]) => fetchAndSaveAppleEvents({ token, email, date: selectedDate }) ); await Promise.all([...googleEvents, ...outlookEvents, ...appleEvents]); setLastSyncDate(selectedDate); setLowerBoundDate(newLowerBound); setUpperBoundDate(newUpperBound); syncedRanges.add(rangeKey); } catch (err) { console.error("Error syncing events:", err); setError(err); } finally { setIsSyncing(false); } } else { setIsSyncing(false); } }, [selectedDate, lowerBoundDate, upperBoundDate, profileData, fetchAndSaveGoogleEvents, fetchAndSaveOutlookEvents, fetchAndSaveAppleEvents, syncedRanges]); useEffect(() => { syncEvents(); }, [selectedDate, syncEvents]); return { isSyncing, error, lastSyncDate, lowerBoundDate, upperBoundDate, }; };