import React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from 'react';
import { THEMES } from '../constants';
import type { Theme, ErrorResponse, AppContextType } from '../types';

const AppContext = createContext<AppContextType | undefined>(undefined);

export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [theme, setTheme] = useState<Theme>(() => {
    try {
      const savedTheme = localStorage.getItem('theme');
      return savedTheme ? JSON.parse(savedTheme) : THEMES.LIGHT;
    } catch {
      return THEMES.LIGHT;
    }
  });
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const toggleTheme = useCallback(() => {
    setTheme(current => {
      const newTheme = current === THEMES.LIGHT ? THEMES.DARK : THEMES.LIGHT;
      try {
        localStorage.setItem('theme', JSON.stringify(newTheme));
      } catch (err) {
        console.warn('Failed to save theme preference:', err);
      }
      return newTheme;
    });
  }, []);

  const clearError = useCallback(() => setError(null), []);

  useEffect(() => {
    const handleError = (event: ErrorEvent) => {
      setError(event.error);
      event.preventDefault();
    };

    const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
      setError(event.reason);
      event.preventDefault();
    };

    window.addEventListener('error', handleError);
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('error', handleError);
      window.removeEventListener('unhandledrejection', handleUnhandledRejection);
    };
  }, []);

  const value = useMemo(() => ({
    theme,
    loading,
    error,
    setLoading,
    setError,
    toggleTheme,
    clearError
  }), [theme, loading, error, toggleTheme, clearError]);

  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );
};

export const useAppContext = () => {
  const context = useContext(AppContext);
  if (context === undefined) {
    throw new Error('useAppContext must be used within an AppProvider');
  }
  return context;
};
