"use client"; import { useEffect, useState } from "react"; import { getStoredPlayer, storePlayer, type StoredPlayer, } from "@/lib/player-store"; import { isSupabaseConfigured } from "@/lib/supabase/client"; import { getOrCreatePlayer, recordPlayerVisit } from "@/lib/supabase/queries"; /** * Hook that ensures the locally-stored player has a real Supabase UUID. * * On mount it reads the player from localStorage. If the player exists but * has an empty `id` and Supabase is configured, it calls * `getOrCreatePlayer(anonymousId, displayName)` and updates localStorage * with the returned UUID. * * @returns `{ player, isLoading }` -- player may be null if none is stored, * and isLoading is true while the Supabase sync is in-flight. */ export function usePlayerSync(): { player: StoredPlayer | null; isLoading: boolean; } { const [player, setPlayer] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { let cancelled = false; async function sync() { const stored = getStoredPlayer(); if (!stored) { setIsLoading(false); return; } setPlayer(stored); // Always verify player exists in DB -- heals stale/reset UUIDs in localStorage if (!isSupabaseConfigured) { setIsLoading(false); return; } try { const dbPlayer = await getOrCreatePlayer( stored.anonymousId, stored.displayName ); if (cancelled) return; if (dbPlayer) { const synced: StoredPlayer = { ...stored, id: dbPlayer.id, }; storePlayer(synced); setPlayer(synced); // Record this session visit in the background recordPlayerVisit(dbPlayer.id).catch(() => {}); } } catch (err) { console.error("[usePlayerSync] failed to sync player:", err); } finally { if (!cancelled) { setIsLoading(false); } } } sync(); return () => { cancelled = true; }; }, []); return { player, isLoading }; }