import React, { createContext, useContext, useState, useCallback, useEffect } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; import type { Beneficiary, BeneficiarySubscription } from '@/types'; const LOCAL_BENEFICIARIES_KEY = 'wellnuo_local_beneficiaries'; interface AddBeneficiaryData { name: string; address?: string; avatar?: string; subscription?: BeneficiarySubscription; } interface BeneficiaryContextType { currentBeneficiary: Beneficiary | null; setCurrentBeneficiary: (beneficiary: Beneficiary | null) => void; clearCurrentBeneficiary: () => void; // Local beneficiaries management (for users without API deployments) localBeneficiaries: Beneficiary[]; addLocalBeneficiary: (data: string | AddBeneficiaryData) => Promise; updateLocalBeneficiary: (id: number, data: Partial) => Promise; removeLocalBeneficiary: (id: number) => Promise; // Clear all data (used on logout) clearAllBeneficiaryData: () => Promise; // Helper to format beneficiary context for AI getBeneficiaryContext: () => string; } const BeneficiaryContext = createContext(undefined); export function BeneficiaryProvider({ children }: { children: React.ReactNode }) { const [currentBeneficiary, setCurrentBeneficiary] = useState(null); const [localBeneficiaries, setLocalBeneficiaries] = useState([]); // Load local beneficiaries on mount useEffect(() => { loadLocalBeneficiaries(); }, []); const loadLocalBeneficiaries = async () => { try { const stored = await AsyncStorage.getItem(LOCAL_BENEFICIARIES_KEY); if (stored) { setLocalBeneficiaries(JSON.parse(stored)); } } catch (error) { console.error('Failed to load local beneficiaries:', error); } }; const saveLocalBeneficiaries = async (beneficiaries: Beneficiary[]) => { try { await AsyncStorage.setItem(LOCAL_BENEFICIARIES_KEY, JSON.stringify(beneficiaries)); } catch (error) { console.error('Failed to save local beneficiaries:', error); } }; const addLocalBeneficiary = useCallback(async (data: string | AddBeneficiaryData): Promise => { // Support both string (legacy) and object format const beneficiaryData: AddBeneficiaryData = typeof data === 'string' ? { name: data } : data; const newBeneficiary: Beneficiary = { id: Date.now(), // Use timestamp as unique ID name: beneficiaryData.name.trim(), displayName: beneficiaryData.name.trim(), // For UI display address: beneficiaryData.address?.trim(), avatar: beneficiaryData.avatar, status: 'offline', last_activity: 'Just added', subscription: beneficiaryData.subscription, }; const updated = [...localBeneficiaries, newBeneficiary]; setLocalBeneficiaries(updated); await saveLocalBeneficiaries(updated); // Auto-select if first beneficiary if (localBeneficiaries.length === 0) { setCurrentBeneficiary(newBeneficiary); } return newBeneficiary; }, [localBeneficiaries]); const updateLocalBeneficiary = useCallback(async (id: number, data: Partial): Promise => { const index = localBeneficiaries.findIndex(b => b.id === id); if (index === -1) return null; const updatedBeneficiary = { ...localBeneficiaries[index], ...data }; const updated = [...localBeneficiaries]; updated[index] = updatedBeneficiary; setLocalBeneficiaries(updated); await saveLocalBeneficiaries(updated); // Update current if it's the same beneficiary if (currentBeneficiary?.id === id) { setCurrentBeneficiary(updatedBeneficiary); } return updatedBeneficiary; }, [localBeneficiaries, currentBeneficiary]); const removeLocalBeneficiary = useCallback(async (id: number) => { const updated = localBeneficiaries.filter(b => b.id !== id); setLocalBeneficiaries(updated); await saveLocalBeneficiaries(updated); // Clear current if removed if (currentBeneficiary?.id === id) { setCurrentBeneficiary(updated[0] || null); } }, [localBeneficiaries, currentBeneficiary]); const clearCurrentBeneficiary = useCallback(() => { setCurrentBeneficiary(null); }, []); // Clear all beneficiary data (called on logout) const clearAllBeneficiaryData = useCallback(async () => { setCurrentBeneficiary(null); setLocalBeneficiaries([]); await AsyncStorage.removeItem(LOCAL_BENEFICIARIES_KEY); }, []); const getBeneficiaryContext = useCallback(() => { if (!currentBeneficiary) { return ''; } const b = currentBeneficiary; const contextParts: string[] = []; // Basic info contextParts.push(`Person: ${b.name}`); if (b.address) { contextParts.push(`Address: ${b.address}`); } // Current status if (b.last_location) { contextParts.push(`Current location: ${b.last_location}`); } if (b.before_last_location) { contextParts.push(`Previous location: ${b.before_last_location}`); } // Health metrics if (b.wellness_score !== undefined) { contextParts.push(`Wellness score: ${b.wellness_score}% (${b.wellness_descriptor || 'N/A'})`); } // Temperature if (b.temperature !== undefined) { const unit = b.units || '°F'; contextParts.push(`Room temperature: ${b.temperature.toFixed(1)}${unit}`); } if (b.bedroom_temperature !== undefined) { const unit = b.units || '°F'; contextParts.push(`Bedroom temperature: ${b.bedroom_temperature.toFixed(1)}${unit}`); } // Sleep data if (b.sleep_hours !== undefined) { contextParts.push(`Sleep hours: ${b.sleep_hours.toFixed(1)} hours`); } // Activity time if (b.last_detected_time) { contextParts.push(`Last detected: ${b.last_detected_time}`); } // Status contextParts.push(`Status: ${b.status === 'online' ? 'Active' : 'Inactive'}`); return `[SENSOR DATA FOR ${b.name.toUpperCase()}: ${contextParts.join('. ')}]`; }, [currentBeneficiary]); return ( {children} ); } export function useBeneficiary() { const context = useContext(BeneficiaryContext); if (context === undefined) { throw new Error('useBeneficiary must be used within a BeneficiaryProvider'); } return context; }