import { useState, useEffect, useCallback } from 'react'; import { invokeWithTracking } from '@/lib/edgeFunctionTracking'; import { useAuth } from '@/hooks/useAuth'; import { supabase } from '@/lib/supabaseClient'; import { handleNonCriticalError } from '@/lib/errorHandler'; import { UnitPreferences, getMeasurementSystemFromCountry } from '@/lib/units'; import type { Json } from '@/integrations/supabase/types'; import * as storage from '@/lib/localStorage'; // Type guard for unit preferences function isValidUnitPreferences(obj: unknown): obj is UnitPreferences { return ( typeof obj === 'object' && obj !== null && 'measurement_system' in obj && (obj.measurement_system === 'metric' || obj.measurement_system === 'imperial') ); } const DEFAULT_PREFERENCES: UnitPreferences = { measurement_system: 'metric', temperature: 'celsius', auto_detect: true }; export function useUnitPreferences() { const { user } = useAuth(); const [preferences, setPreferences] = useState(DEFAULT_PREFERENCES); const [loading, setLoading] = useState(true); useEffect(() => { loadPreferences(); }, [user]); const loadPreferences = async () => { try { if (user) { const { data, error } = await supabase .from('user_preferences') .select('unit_preferences') .eq('user_id', user.id) .maybeSingle(); if (error && error.code !== 'PGRST116') { handleNonCriticalError(error, { action: 'Fetch unit preferences', userId: user.id, }); throw error; } if (data?.unit_preferences && isValidUnitPreferences(data.unit_preferences)) { const validPrefs = data.unit_preferences as UnitPreferences; setPreferences({ ...DEFAULT_PREFERENCES, ...validPrefs }); } else { await autoDetectPreferences(); } } else { const stored = localStorage.getItem('unit_preferences'); if (stored) { try { const parsed = JSON.parse(stored); setPreferences({ ...DEFAULT_PREFERENCES, ...parsed }); } catch (e) { await autoDetectPreferences(); } } else { await autoDetectPreferences(); } } } catch (error: unknown) { handleNonCriticalError(error, { action: 'Load unit preferences', userId: user?.id, }); await autoDetectPreferences(); } finally { setLoading(false); } }; const autoDetectPreferences = useCallback(async () => { try { const response = await invokeWithTracking('detect-location', {}, user?.id); if (response.data && response.data.measurementSystem) { const newPreferences: UnitPreferences = { ...DEFAULT_PREFERENCES, measurement_system: response.data.measurementSystem, }; setPreferences(newPreferences); if (user) { const { error } = await supabase .from('user_preferences') .upsert({ user_id: user.id, unit_preferences: newPreferences as unknown as Json, updated_at: new Date().toISOString() }, { onConflict: 'user_id' }); if (error) { handleNonCriticalError(error, { action: 'Save auto-detected preferences', userId: user.id, }); } } else { localStorage.setItem('unit_preferences', JSON.stringify(newPreferences)); } return newPreferences; } } catch (error: unknown) { handleNonCriticalError(error, { action: 'Auto-detect location', userId: user?.id, }); } // Fallback to default setPreferences(DEFAULT_PREFERENCES); return DEFAULT_PREFERENCES; }, [user]); const updatePreferences = async (newPreferences: Partial) => { const updated = { ...preferences, ...newPreferences }; setPreferences(updated); try { if (user) { await supabase .from('user_preferences') .update({ unit_preferences: updated as unknown as Json, updated_at: new Date().toISOString() }) .eq('user_id', user.id); } else { storage.setJSON('unit_preferences', updated); } } catch (error: unknown) { handleNonCriticalError(error, { action: 'Save unit preferences', userId: user?.id, }); setPreferences(preferences); throw error; } }; return { preferences, loading, updatePreferences, autoDetectPreferences }; }