import React, { Suspense, useCallback, useMemo } from 'react';
import ErrorBoundary from './ErrorBoundary';
import LoadingSpinner from './LoadingSpinner';
import { AppContainer, AppHeader } from './styles/AppStyles';
import { APP_TITLE, APP_DESCRIPTION } from '../constants';
import { useAppContext } from '../contexts/AppContext';
import type { BaseProps, Theme } from '../types';

export interface AppProps extends BaseProps {
  onError?: (error: Error, info?: React.ErrorInfo) => void;
  fallbackComponent?: React.ReactNode;
  initialTheme?: Theme;
}

const App: React.FC<AppProps> = React.memo(({ 
  className = '',
  testId = 'app-root',
  onError,
  fallbackComponent,
  initialTheme
}) => {
  const { theme = initialTheme, loading, error, clearError } = useAppContext();

  const handleError = useCallback((error: Error, info?: React.ErrorInfo) => {
    onError?.(error, info);
    console.error('[App Error]:', { 
      error: error.message, 
      stack: error.stack,
      info, 
      timestamp: new Date().toISOString(),
      environment: process.env.NODE_ENV
    });
  }, [onError]);

  const handleRetry = useCallback(() => {
    clearError();
    // Use a more controlled approach for reload
    window.location.href = window.location.pathname;
  }, [clearError]);

  const containerClasses = useMemo(() => {
    return `app ${className || ''}`.trim();
  }, [className]);

  const mainContent = useMemo(() => (
    <AppHeader theme={theme}>
      <h1 
        tabIndex={0} 
        aria-label={APP_TITLE}
        role="heading"
        aria-level={1}
        data-testid="app-title"
      >
        {APP_TITLE}
      </h1>
      <p 
        tabIndex={0}
        aria-label={APP_DESCRIPTION}
        role="contentinfo"
        data-testid="app-description"
      >
        {APP_DESCRIPTION}
      </p>
    </AppHeader>
  ), [theme]);

  if (error) {
    return (
      <ErrorBoundary 
        error={error} 
        onError={handleError}
        onRetry={handleRetry}
        fallback={fallbackComponent}
        testId="app-error-boundary"
      />
    );
  }

  return (
    <ErrorBoundary 
      onError={handleError} 
      onRetry={handleRetry}
      testId="global-error-boundary"
    >
      <Suspense 
        fallback={
          <LoadingSpinner 
            size="large" 
            aria-label="Loading application..."
            testId="app-loading"
            color={theme?.primary}
          />
        }
      >
        <AppContainer 
          className={containerClasses}
          data-testid={testId}
          role="main"
          theme={theme}
          aria-busy={loading}
          aria-live="polite"
        >
          {loading ? (
            <LoadingSpinner 
              size="medium" 
              aria-label="Loading content..."
              color={theme?.primary}
              testId="content-loading"
              message="Please wait while content loads..."
            />
          ) : mainContent}
        </AppContainer>
      </Suspense>
    </ErrorBoundary>
  );
});

App.displayName = 'App';

export default App;