"use client"; import React, { createContext, useContext, useEffect, useState, ReactNode, useCallback, } from "react"; import { useAuth } from "@/contexts/AuthContext"; import { type UserProfile as ApiUserProfile, getUserProfile, saveApiKey, updateUserProfile, } from "@/app/lib/mikeApi"; interface UserProfile { displayName: string | null; organisation: string | null; messageCreditsUsed: number; creditsResetDate: string; creditsRemaining: number; tier: string; tabularModel: string; claudeApiKey: string | null; geminiApiKey: string | null; } interface UserProfileContextType { profile: UserProfile | null; loading: boolean; updateDisplayName: (name: string) => Promise; updateOrganisation: (organisation: string) => Promise; updateModelPreference: ( field: "tabularModel", value: string, ) => Promise; updateApiKey: ( provider: "claude" | "gemini", value: string | null, ) => Promise; reloadProfile: () => Promise; incrementMessageCredits: () => Promise; } const UserProfileContext = createContext( undefined, ); const CONFIGURED_KEY_MARKER = "configured"; function toProfile(data: ApiUserProfile): UserProfile { const { apiKeyStatus, ...profile } = data; return { ...profile, claudeApiKey: apiKeyStatus.claude ? CONFIGURED_KEY_MARKER : null, geminiApiKey: apiKeyStatus.gemini ? CONFIGURED_KEY_MARKER : null, }; } export function UserProfileProvider({ children }: { children: ReactNode }) { const { user, isAuthenticated } = useAuth(); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const loadProfile = useCallback(async () => { try { const profileData = await getUserProfile(); setProfile(toProfile(profileData)); } catch { // Calculate a default future reset date for fallback const futureResetDate = new Date(); futureResetDate.setDate(futureResetDate.getDate() + 30); // Set fallback profile data on exception setProfile({ displayName: null, organisation: null, messageCreditsUsed: 0, creditsResetDate: futureResetDate.toISOString(), creditsRemaining: 999999, // temporarily unlimited tier: "Free", tabularModel: "gemini-3-flash-preview", claudeApiKey: null, geminiApiKey: null, }); } finally { setLoading(false); } }, []); useEffect(() => { if (isAuthenticated && user) { setLoading(true); loadProfile(); } else { setProfile(null); setLoading(false); } }, [isAuthenticated, user, loadProfile]); const updateDisplayName = useCallback( async (displayName: string): Promise => { if (!user) { return false; } try { const updated = await updateUserProfile({ displayName }); setProfile((prev) => prev ? { ...prev, ...toProfile(updated) } : null, ); return true; } catch { return false; } }, [user], ); const updateOrganisation = useCallback( async (organisation: string): Promise => { if (!user) return false; try { const updated = await updateUserProfile({ organisation }); setProfile((prev) => prev ? { ...prev, ...toProfile(updated) } : null, ); return true; } catch { return false; } }, [user], ); const updateModelPreference = useCallback( async (field: "tabularModel", value: string): Promise => { if (!user) return false; if (field !== "tabularModel") return false; try { const updated = await updateUserProfile({ tabularModel: value, }); setProfile((prev) => prev ? { ...prev, ...toProfile(updated) } : null, ); return true; } catch { return false; } }, [user], ); const updateApiKey = useCallback( async ( provider: "claude" | "gemini", value: string | null, ): Promise => { if (!user) return false; const stateField = provider === "claude" ? "claudeApiKey" : "geminiApiKey"; const normalized = value?.trim() ? value.trim() : null; try { await saveApiKey(provider, normalized); setProfile((prev) => prev ? { ...prev, [stateField]: normalized ? CONFIGURED_KEY_MARKER : null, } : null, ); return true; } catch { return false; } }, [user], ); const reloadProfile = useCallback(async () => { if (user) { await loadProfile(); } }, [user, loadProfile]); const incrementMessageCredits = useCallback(async (): Promise => { if (!user || !profile) { return false; } // Check if user has credits remaining if (profile.creditsRemaining <= 0) { return false; } return false; }, [user, profile]); return ( {children} ); } export function useUserProfile() { const context = useContext(UserProfileContext); if (context === undefined) { throw new Error( "useUserProfile must be used within a UserProfileProvider", ); } return context; }