/**
 * Error Boundary Component
 * 
 * Catches JavaScript errors anywhere in the component tree,
 * logs those errors, and displays a fallback UI.
 * 
 * Features:
 * - Catches rendering errors
 * - Logs errors with context
 * - Displays user-friendly error message
 * - Provides recovery options
 * - Integrates with error reporting
 */

'use client';

import React, { Component, ErrorInfo, ReactNode } from 'react';
import { AlertTriangle, RefreshCw, Home, Bug } from 'lucide-react';
import { logger } from '@/lib/utils/logger';
import { errorReporter } from '@/lib/utils/errorReporter';

interface ErrorBoundaryProps {
  /** Child components */
  children: ReactNode;
  /** Fallback UI (optional) */
  fallback?: ReactNode | ((error: Error, errorInfo: ErrorInfo, reset: () => void) => ReactNode);
  /** Error boundary name for logging */
  name?: string;
  /** Callback when error occurs */
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
  /** Show detailed error in development */
  showDetails?: boolean;
}

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

/**
 * Error Boundary Component
 * 
 * @example
 * ```tsx
 * <ErrorBoundary name="Canvas">
 *   <Canvas />
 * </ErrorBoundary>
 * ```
 */
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {
    // Update state so the next render will show the fallback UI
    return {
      hasError: true,
      error,
    };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    const { name = 'ErrorBoundary', onError } = this.props;

    // Log error
    logger.error(`[${name}] Caught error:`, error, errorInfo);

    // Report error with metadata instead of context
    if (typeof window !== 'undefined') {
      errorReporter.report(
        error,
        {
          component: name,
          componentStack: errorInfo.componentStack,
        }
      );
    }

    // Update state with error info
    this.setState({
      errorInfo,
    });

    // Call custom error handler
    if (onError) {
      onError(error, errorInfo);
    }
  }

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

  handleReload = () => {
    window.location.reload();
  };

  handleGoHome = () => {
    window.location.href = '/';
  };

  render() {
    const { hasError, error, errorInfo } = this.state;
    const { children, fallback, name = 'ErrorBoundary', showDetails = process.env.NODE_ENV === 'development' } = this.props;

    if (hasError && error) {
      // Use custom fallback if provided
      if (fallback) {
        if (typeof fallback === 'function') {
          return fallback(error, errorInfo!, this.handleReset);
        }
        return fallback;
      }

      // Default fallback UI
      return (
        <div className="min-h-screen flex items-center justify-center bg-gray-50 px-4">
          <div className="max-w-2xl w-full bg-white rounded-lg shadow-lg p-8">
            {/* Error Icon */}
            <div className="flex justify-center mb-6">
              <div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center">
                <AlertTriangle className="w-8 h-8 text-red-600" />
              </div>
            </div>

            {/* Error Title */}
            <h1 className="text-2xl font-bold text-gray-900 text-center mb-2">
              出错了
            </h1>
            <p className="text-gray-600 text-center mb-6">
              {name} 遇到了一个错误，我们已经记录了这个问题
            </p>

            {/* Error Message */}
            <div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
              <div className="flex gap-2">
                <Bug className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" />
                <div className="flex-1">
                  <p className="text-sm font-medium text-red-900 mb-1">
                    错误信息
                  </p>
                  <p className="text-sm text-red-800 font-mono">
                    {error.message || '未知错误'}
                  </p>
                </div>
              </div>
            </div>

            {/* Error Details (Development Only) */}
            {showDetails && errorInfo && (
              <details className="mb-6">
                <summary className="text-sm font-medium text-gray-700 cursor-pointer hover:text-gray-900 mb-2">
                  技术详情（开发模式）
                </summary>
                <div className="bg-gray-50 border border-gray-200 rounded-lg p-4 overflow-auto max-h-64">
                  <pre className="text-xs text-gray-700 whitespace-pre-wrap font-mono">
                    {error.stack}
                    {'\n\n'}
                    {errorInfo.componentStack}
                  </pre>
                </div>
              </details>
            )}

            {/* Actions */}
            <div className="flex flex-col sm:flex-row gap-3">
              <button
                onClick={this.handleReset}
                className="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
              >
                <RefreshCw className="w-5 h-5" />
                <span>重试</span>
              </button>
              
              <button
                onClick={this.handleReload}
                className="flex-1 flex items-center justify-center gap-2 px-4 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
              >
                <RefreshCw className="w-5 h-5" />
                <span>刷新页面</span>
              </button>
              
              <button
                onClick={this.handleGoHome}
                className="flex-1 flex items-center justify-center gap-2 px-4 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
              >
                <Home className="w-5 h-5" />
                <span>返回首页</span>
              </button>
            </div>

            {/* Help Text */}
            <p className="text-xs text-gray-500 text-center mt-6">
              如果问题持续存在，请联系技术支持或使用&ldquo;报告问题&rdquo;功能
            </p>
          </div>
        </div>
      );
    }

    return children;
  }
}

/**
 * Hook-based Error Boundary (for functional components)
 * Note: This is a wrapper around the class-based ErrorBoundary
 */
export function useErrorBoundary() {
  const [error, setError] = React.useState<Error | null>(null);

  React.useEffect(() => {
    if (error) {
      throw error;
    }
  }, [error]);

  const resetError = React.useCallback(() => {
    setError(null);
  }, []);

  return {
    error,
    setError,
    resetError,
  };
}

/**
 * Canvas Error Boundary
 * Specialized error boundary for Canvas component
 */
export function CanvasErrorBoundary({ children }: { children: ReactNode }) {
  return (
    <ErrorBoundary
      name="Canvas"
      fallback={(error, errorInfo, reset) => (
        <div className="flex items-center justify-center h-full bg-gray-50">
          <div className="max-w-md w-full bg-white rounded-lg shadow-lg p-6">
            <div className="flex justify-center mb-4">
              <div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center">
                <AlertTriangle className="w-6 h-6 text-red-600" />
              </div>
            </div>
            <h2 className="text-lg font-semibold text-gray-900 text-center mb-2">
              画布加载失败
            </h2>
            <p className="text-sm text-gray-600 text-center mb-4">
              {error.message}
            </p>
            <button
              onClick={reset}
              className="w-full flex items-center justify-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
            >
              <RefreshCw className="w-4 h-4" />
              <span>重新加载画布</span>
            </button>
          </div>
        </div>
      )}
    >
      {children}
    </ErrorBoundary>
  );
}

export default ErrorBoundary;
