import { useState, useCallback, useMemo } from 'react'; import pb from '../lib/pocketbase'; import { trackEvent } from '../lib/analytics'; import type { Property } from '../types'; import { getNum } from '../lib/property-fields'; export interface SavedPropertyData { propertyType?: string; propertySubType?: string; builtForm?: string; duration?: string; energyRating?: string; price?: number; estimatedPrice?: number; askingPrice?: number; askingRent?: number; bedrooms?: number; floorArea?: number; listingUrl?: string; } export interface SavedProperty { id: string; address: string; postcode: string; data: SavedPropertyData; created: string; } export function useSavedProperties(userId: string | null) { const [properties, setProperties] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const fetchProperties = useCallback(async () => { if (!userId) return; setLoading(true); setError(null); try { const records = await pb.collection('saved_properties').getFullList({ sort: '-created', filter: `user = "${userId}"`, }); setProperties( records.map((r) => { const raw = r as Record; let data: SavedPropertyData = {}; try { data = typeof raw.data === 'string' ? JSON.parse(raw.data) : (raw.data as SavedPropertyData) || {}; } catch { // Invalid JSON — use empty data } return { id: r.id, address: raw.address as string, postcode: raw.postcode as string, data, created: r.created, }; }) ); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load saved properties'); } finally { setLoading(false); } }, [userId]); const saveProperty = useCallback( async (property: Property) => { if (!userId) return; setError(null); try { const data: SavedPropertyData = { propertyType: property.property_type, propertySubType: property.property_sub_type, builtForm: property.built_form, duration: property.duration, energyRating: property.current_energy_rating, price: getNum(property, 'Last known price'), estimatedPrice: getNum(property, 'Estimated current price'), askingPrice: getNum(property, 'Asking price'), askingRent: getNum(property, 'Asking rent (monthly)'), bedrooms: getNum(property, 'Bedrooms'), floorArea: getNum(property, 'Total floor area (sqm)'), listingUrl: property.listing_url || undefined, }; await pb.collection('saved_properties').create({ user: userId, address: property.address || 'Unknown', postcode: property.postcode || '', data: JSON.stringify(data), }); trackEvent('Property Save'); await fetchProperties(); } catch (err) { const msg = err instanceof Error ? err.message : 'Failed to save property'; setError(msg); } }, [userId, fetchProperties] ); const deleteProperty = useCallback(async (id: string) => { setError(null); try { await pb.collection('saved_properties').delete(id); trackEvent('Property Delete'); setProperties((prev) => prev.filter((p) => p.id !== id)); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete property'); } }, []); const savedPropertyKeys = useMemo( () => new Set(properties.map((p) => `${p.address}|${p.postcode}`)), [properties] ); const isPropertySaved = useCallback( (address?: string, postcode?: string) => savedPropertyKeys.has(`${address || ''}|${postcode || ''}`), [savedPropertyKeys] ); const getSavedPropertyId = useCallback( (address?: string, postcode?: string) => { const key = `${address || ''}|${postcode || ''}`; return properties.find((p) => `${p.address}|${p.postcode}` === key)?.id; }, [properties] ); return { properties, loading, error, fetchProperties, saveProperty, deleteProperty, isPropertySaved, getSavedPropertyId, }; }