import React, { Component, ReactNode } from 'react';

interface Props {
  children: ReactNode;
  componentName?: string;
}

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

class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false, error: null, errorInfo: null };
  }

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

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('ErrorBoundary caught an error:', error, errorInfo);
    this.setState({
      error,
      errorInfo
    });
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: null, errorInfo: null });
  };

  handleCopyError = () => {
    const { error, errorInfo } = this.state;
    const { componentName } = this.props;

    const errorText = `
Component: ${componentName || 'Unknown'}
Error: ${error?.message || 'Unknown error'}
Stack: ${error?.stack || 'No stack trace available'}
Component Stack: ${errorInfo?.componentStack || 'No component stack available'}
Timestamp: ${new Date().toISOString()}
    `.trim();

    navigator.clipboard.writeText(errorText).then(() => {
      alert('Error details copied to clipboard!');
    }).catch(() => {
      // Fallback for older browsers
      const textArea = document.createElement('textarea');
      textArea.value = errorText;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand('copy');
      document.body.removeChild(textArea);
      alert('Error details copied to clipboard!');
    });
  };

  render() {
    if (this.state.hasError) {
      const { componentName } = this.props;
      const { error, errorInfo } = this.state;

      return (
        <div className="flex flex-col items-center justify-center p-8 bg-red-50 border border-red-200 rounded-lg m-4">
          <div className="text-center mb-6">
            <h2 className="text-xl font-semibold text-red-800 mb-2">
              Sorry, something went wrong
            </h2>
            <p className="text-red-600 mb-4">
              {componentName ? `An error occurred in the ${componentName} component.` : 'An unexpected error occurred.'}
            </p>
            <button
              onClick={this.handleRetry}
              className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors mr-2"
            >
              Try Again
            </button>
            <button
              onClick={this.handleCopyError}
              className="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
            >
              Copy Error Details
            </button>
          </div>

          <details className="w-full max-w-4xl">
            <summary className="cursor-pointer text-red-700 font-medium mb-2 hover:text-red-800">
              Show Error Details (for developers)
            </summary>
            <div className="bg-gray-100 p-4 rounded border text-sm font-mono overflow-auto max-h-96">
              <div className="mb-4">
                <strong className="text-red-700">Error Message:</strong>
                <pre className="mt-1 whitespace-pre-wrap text-red-800">
                  {error?.message || 'Unknown error'}
                </pre>
              </div>

              <div className="mb-4">
                <strong className="text-red-700">Stack Trace:</strong>
                <pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs">
                  {error?.stack || 'No stack trace available'}
                </pre>
              </div>

              {errorInfo?.componentStack && (
                <div className="mb-4">
                  <strong className="text-red-700">Component Stack:</strong>
                  <pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs">
                    {errorInfo.componentStack}
                  </pre>
                </div>
              )}

              <div className="text-xs text-gray-600">
                <strong>Timestamp:</strong> {new Date().toISOString()}
              </div>
            </div>
          </details>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;
