"use server"; import { revalidatePath } from "next/cache"; import type { GarminConnect } from "garmin-connect"; import { GarminLoginRequiredError, beginGarminLogin, completeGarminMfaLogin, fetchActivityRoutePoints, fetchRunningActivities, getAuthorizedClient, } from "@/lib/garmin/client"; import { getLastSyncAt, getRunningActivity, setLastSyncAt, setRunningActivityRoutePoints, upsertRunningActivity, } from "@/lib/models/running"; import { clearPendingMfaState, getPendingMfaState, saveOauth1Token, savePendingMfaState, } from "@/lib/models/garmin-auth"; export type SyncGarminState = { error: string } | { success: string } | { mfaRequired: true } | null; async function syncWithClient(client: GarminConnect): Promise { const since = await getLastSyncAt(); const activities = await fetchRunningActivities(client); const newCount = activities.filter((activity) => !since || activity.startTime > since).length; for (const activity of activities) { await upsertRunningActivity(activity); } await setLastSyncAt(new Date()); revalidatePath("/running"); revalidatePath("/settings"); revalidatePath("/"); return { success: `Zsynchronizowano ${newCount} nowych aktywności (zaktualizowano ${activities.length}).` }; } export async function syncGarminActivities(): Promise { try { const client = await getAuthorizedClient(); return await syncWithClient(client); } catch (error) { if (!(error instanceof GarminLoginRequiredError)) { return { error: error instanceof Error ? error.message : "Synchronizacja z Garmin nie powiodła się." }; } } try { const result = await beginGarminLogin(); if ("mfaRequired" in result) { await savePendingMfaState(result.pendingState); return { mfaRequired: true }; } await saveOauth1Token(result.oauth1Token); return await syncWithClient(result.client); } catch (error) { return { error: error instanceof Error ? error.message : "Logowanie do Garmin nie powiodło się." }; } } export async function submitGarminMfaCode(code: string): Promise { const pending = await getPendingMfaState(); if (!pending) { return { error: "Sesja logowania do Garmin wygasła. Kliknij \"Synchronizuj z Garmin\" ponownie." }; } try { const result = await completeGarminMfaLogin(pending, code); await saveOauth1Token(result.oauth1Token); await clearPendingMfaState(); return await syncWithClient(result.client); } catch (error) { return { error: error instanceof Error ? error.message : "Weryfikacja kodu MFA nie powiodła się." }; } } export type LoadRouteState = { error: string } | { success: true } | null; export async function loadActivityRoute(activityMongoId: string): Promise { const activity = await getRunningActivity(activityMongoId); if (!activity) return { error: "Nie znaleziono aktywności." }; let client: GarminConnect; try { client = await getAuthorizedClient(); } catch { return { error: "Brak połączenia z Garmin Connect. Wykonaj synchronizację." }; } try { const points = await fetchActivityRoutePoints(client, activity.garminActivityId); if (!points) return { error: "Brak danych GPS dla tej aktywności." }; await setRunningActivityRoutePoints(activity.garminActivityId, points); revalidatePath(`/running/${activityMongoId}`); return { success: true }; } catch (error) { return { error: error instanceof Error ? error.message : "Nie udało się pobrać mapy trasy." }; } }