import React, { Component, ErrorInfo } from 'react';
import { ERROR_MESSAGES } from '../constants';
import { ErrorContainer, ErrorMessage, RetryButton } from './styles/ErrorStyles';
import type { ErrorResponse, ErrorBoundaryProps } from '../types';

interface State {
  hasError: boolean;
  error: Error | null;
  errorInfo: ErrorInfo | null;
}

export class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
  private retryAttempts: number = 0;
  private readonly MAX_RETRY_ATTEMPTS = 3;

  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = {
      hasError: Boolean(props.error),
      error: props.error || null,
      errorInfo: null
    };
  }

  static getDerivedStateFromError(error: Error): State {
    return {
      hasError: true,
      error,
      errorInfo: null
    };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
    this.setState({ errorInfo });
    this.props.onError?.(error, errorInfo);

    // Log to monitoring service in production
    if (process.env.NODE_ENV === 'production') {
      // Implement error logging service here
      console.error('[ErrorBoundary]', {
        error: error.message,
        stack: error.stack,
        componentStack: errorInfo.componentStack,
        timestamp: new Date().toISOString()
      });
    }
  }

  private getErrorMessage(error: Error | null): string {
    if (!error) return ERROR_MESSAGES.GENERIC;
    
    if ((error as ErrorResponse).code) {
      const errorResponse = error as ErrorResponse;
      return ERROR_MESSAGES[errorResponse.code] || errorResponse.message;
    }
    
    return error.message || ERROR_MESSAGES.GENERIC;
  }

  private handleRetry = (): void => {
    if (this.retryAttempts >= this.MAX_RETRY_ATTEMPTS) {
      alert('Maximum retry attempts reached. Please refresh the page.');
      return;
    }

    this.retryAttempts++;
    this.setState({ hasError: false, error: null, errorInfo: null });
    this.props.onRetry?.();
  };

  render(): React.ReactNode {
    const { hasError, error } = this.state;
    const { fallback, testId = 'error-boundary' } = this.props;

    if (hasError) {
      return fallback || (
        <ErrorContainer 
          role="alert" 
          aria-live="assertive"
          data-testid={testId}
        >
          <h2>An Error Occurred</h2>
          <ErrorMessage data-testid="error-message">
            {this.getErrorMessage(error)}
          </ErrorMessage>
          <RetryButton 
            onClick={this.handleRetry}
            aria-label="Retry loading the application"
            data-testid="retry-button"
            disabled={this.retryAttempts >= this.MAX_RETRY_ATTEMPTS}
          >
            {this.retryAttempts >= this.MAX_RETRY_ATTEMPTS ? 
              'Maximum retries reached' : 'Retry'}
          </RetryButton>
        </ErrorContainer>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;