import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import type { ReactNode } from 'react'; import { DEFAULT_THEME, THEME_STORAGE_KEY, resolveInitialTheme, themeClassName, type ThemeName, } from './tokens'; interface ThemeContextValue { theme: ThemeName; toggleTheme: () => void; } const ThemeContext = createContext(undefined); function readStoredTheme(): string | null { try { return window.localStorage.getItem(THEME_STORAGE_KEY); } catch { // BR-3: treat unavailable/unreadable storage the same as "nothing stored" — fall back to default. return null; } } function persistTheme(theme: ThemeName): void { try { window.localStorage.setItem(THEME_STORAGE_KEY, theme); } catch { // Ignore write failures (e.g. storage disabled) — theme still works for this session via state. } } export function ThemeProvider({ children }: { children: ReactNode }) { const [theme, setTheme] = useState(() => resolveInitialTheme(readStoredTheme())); useEffect(() => { const root = document.documentElement; root.classList.remove('theme-red', 'theme-purple'); root.classList.add(themeClassName(theme)); }, [theme]); const toggleTheme = useCallback(() => { setTheme((current) => { const next: ThemeName = current === 'red' ? 'purple' : 'red'; persistTheme(next); return next; }); }, []); const value = useMemo(() => ({ theme, toggleTheme }), [theme, toggleTheme]); return {children}; } export function useTheme(): ThemeContextValue { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; } export { DEFAULT_THEME };