import { useState, useEffect, useCallback } from 'react' import * as SecureStore from 'expo-secure-store' import NetInfo from '@react-native-community/netinfo' interface CacheOptions { ttlMs?: number // 캐시 유효 시간 (ms), 기본 5분 } export function useOfflineCache( cacheKey: string, fetcher: () => Promise<{ data: T }>, options: CacheOptions = {} ) { const { ttlMs = 5 * 60 * 1000 } = options const [data, setData] = useState(null) const [isOffline, setOffline] = useState(false) const [loading, setLoading] = useState(true) const [cachedAt, setCachedAt] = useState(null) useEffect(() => { const unsub = NetInfo.addEventListener(state => { setOffline(!(state.isConnected ?? true)) }) return () => unsub() }, []) const load = useCallback(async () => { setLoading(true) try { if (!isOffline) { const result = await fetcher() setData(result.data) const now = new Date() setCachedAt(now) await SecureStore.setItemAsync(cacheKey, JSON.stringify({ data: result.data, ts: now.toISOString(), })) } else { const raw = await SecureStore.getItemAsync(cacheKey) if (raw) { const { data: cached, ts } = JSON.parse(raw) const age = Date.now() - new Date(ts).getTime() setData(cached) setCachedAt(new Date(ts)) if (age > ttlMs) { console.warn(`[OfflineCache] ${cacheKey} 캐시 만료 (${Math.floor(age / 60000)}분 전)`) } } } } catch { const raw = await SecureStore.getItemAsync(cacheKey) if (raw) { const { data: cached, ts } = JSON.parse(raw) setData(cached); setCachedAt(new Date(ts)) } } finally { setLoading(false) } }, [cacheKey, fetcher, isOffline, ttlMs]) useEffect(() => { load() }, [load]) return { data, isOffline, loading, cachedAt, reload: load } }