import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { THEME_LABELS, type SiteTheme } from '../data/content';

const STORAGE_KEY = 'embrace-theme';
const ACCESSIBILITY_KEY = 'embrace-a11y';

export type FontSizeLevel = 'normal' | 'large' | 'xlarge';

type ThemeContextValue = {
  theme: SiteTheme;
  setTheme: (theme: SiteTheme) => void;
  themes: SiteTheme[];
  themeLabels: typeof THEME_LABELS;
  fontSize: FontSizeLevel;
  setFontSize: (size: FontSizeLevel) => void;
  highContrast: boolean;
  setHighContrast: (enabled: boolean) => void;
  dyslexicFont: boolean;
  setDyslexicFont: (enabled: boolean) => void;
  resetAccessibility: () => void;
};

const ThemeContext = createContext<ThemeContextValue | null>(null);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setThemeState] = useState<SiteTheme>(() => {
    if (typeof window === 'undefined') return 'embrace';
    const stored = localStorage.getItem(STORAGE_KEY) as SiteTheme | null;
    if (stored && stored in THEME_LABELS) return stored;
    return 'embrace';
  });

  const [fontSize, setFontSizeState] = useState<FontSizeLevel>(() => {
    if (typeof window === 'undefined') return 'normal';
    try {
      const stored = localStorage.getItem(`${ACCESSIBILITY_KEY}-font`);
      if (stored === 'large' || stored === 'xlarge') return stored;
    } catch {
      // ignore
    }
    return 'normal';
  });

  const [highContrast, setHighContrastState] = useState<boolean>(() => {
    if (typeof window === 'undefined') return false;
    return localStorage.getItem(`${ACCESSIBILITY_KEY}-contrast`) === 'true';
  });

  const [dyslexicFont, setDyslexicFontState] = useState<boolean>(() => {
    if (typeof window === 'undefined') return false;
    return localStorage.getItem(`${ACCESSIBILITY_KEY}-dyslexic`) === 'true';
  });

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem(STORAGE_KEY, theme);
  }, [theme]);

  useEffect(() => {
    document.documentElement.setAttribute('data-font-size', fontSize);
    localStorage.setItem(`${ACCESSIBILITY_KEY}-font`, fontSize);
  }, [fontSize]);

  useEffect(() => {
    document.documentElement.setAttribute('data-high-contrast', highContrast ? 'true' : 'false');
    localStorage.setItem(`${ACCESSIBILITY_KEY}-contrast`, String(highContrast));
  }, [highContrast]);

  useEffect(() => {
    document.documentElement.setAttribute('data-dyslexic', dyslexicFont ? 'true' : 'false');
    localStorage.setItem(`${ACCESSIBILITY_KEY}-dyslexic`, String(dyslexicFont));
  }, [dyslexicFont]);

  const setTheme = useCallback((next: SiteTheme) => {
    setThemeState(next);
  }, []);

  const setFontSize = useCallback((size: FontSizeLevel) => {
    setFontSizeState(size);
  }, []);

  const setHighContrast = useCallback((enabled: boolean) => {
    setHighContrastState(enabled);
  }, []);

  const setDyslexicFont = useCallback((enabled: boolean) => {
    setDyslexicFontState(enabled);
  }, []);

  const resetAccessibility = useCallback(() => {
    setThemeState('embrace');
    setFontSizeState('normal');
    setHighContrastState(false);
    setDyslexicFontState(false);

    try {
      localStorage.removeItem(STORAGE_KEY);
      localStorage.removeItem(`${ACCESSIBILITY_KEY}-font`);
      localStorage.removeItem(`${ACCESSIBILITY_KEY}-contrast`);
      localStorage.removeItem(`${ACCESSIBILITY_KEY}-dyslexic`);
    } catch {
      // ignore
    }
  }, []);

  const value = useMemo(
    () => ({
      theme,
      setTheme,
      themes: Object.keys(THEME_LABELS) as SiteTheme[],
      themeLabels: THEME_LABELS,
      fontSize,
      setFontSize,
      highContrast,
      setHighContrast,
      dyslexicFont,
      setDyslexicFont,
      resetAccessibility,
    }),
    [theme, setTheme, fontSize, setFontSize, highContrast, setHighContrast, dyslexicFont, setDyslexicFont, resetAccessibility],
  );

  return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
}

export function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error('useTheme must be used within ThemeProvider');
  return ctx;
}
