import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react' import { Appearance } from 'react-native' import AsyncStorage from '@react-native-async-storage/async-storage' import { makeTheme, type ThemeMode, type ThemeTokens } from './ItmsTheme' /* * ITMS 테마 컨텍스트 — 단일 브랜드(WISE 블루) × 모드(LIGHT/DARK/SYSTEM). * 로컬 AsyncStorage 영속(오프라인). ITMS 백엔드에는 별도 preferences API 가 없어 서버 동기 없음. */ export type PrefMode = ThemeMode | 'system' const MODE_KEY = 'itms_theme_mode' interface ThemeContextValue { t: ThemeTokens resolved: ThemeMode mode: PrefMode setMode: (m: PrefMode) => void } function systemMode(): ThemeMode { return Appearance.getColorScheme() === 'light' ? 'light' : 'dark' } const ThemeContext = createContext(null) export function ThemeProvider({ children }: { children: ReactNode }) { const [mode, setModeState] = useState('light') const [sysScheme, setSysScheme] = useState(systemMode()) useEffect(() => { let alive = true AsyncStorage.getItem(MODE_KEY) .then((v) => { if (!alive) return if (v === 'dark' || v === 'light' || v === 'system') setModeState(v) }) .catch(() => { /* 접근 실패 무시 */ }) return () => { alive = false } }, []) useEffect(() => { const sub = Appearance.addChangeListener(({ colorScheme }) => { setSysScheme(colorScheme === 'light' ? 'light' : 'dark') }) return () => sub.remove() }, []) const setMode = useCallback((m: PrefMode) => { setModeState(m) AsyncStorage.setItem(MODE_KEY, m).catch(() => { /* noop */ }) }, []) const resolved: ThemeMode = mode === 'system' ? sysScheme : mode const value = useMemo( () => ({ t: makeTheme(resolved), resolved, mode, setMode }), [resolved, mode, setMode] ) return {children} } /** 테마 훅. Provider 외부 호출 시 라이트 폴백(방어적). */ export function useTheme(): ThemeContextValue { const ctx = useContext(ThemeContext) if (ctx) return ctx return { t: makeTheme('light'), resolved: 'light', mode: 'light', setMode: () => { /* noop */ } } }