import React, { Component, ErrorInfo, ReactNode } from 'react';
import { clsx } from 'clsx';
import { Button } from '../../ui';

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

export interface ErrorBoundaryProps {
  /** Componentes hijos */
  children: ReactNode;
  /** Componente de fallback personalizado */
  fallback?: (error: Error, errorInfo: ErrorInfo, retry: () => void) => ReactNode;
  /** Función llamada cuando ocurre un error */
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
  /** Mostrar información detallada del error en desarrollo */
  showDetails?: boolean;
  /** Título personalizado del error */
  title?: string;
  /** Descripción personalizada del error */
  description?: string;
  /** Habilitar botón de recarga */
  enableReload?: boolean;
  /** Habilitar botón de reintentar */
  enableRetry?: boolean;
  /** Habilitar navegación hacia atrás */
  enableGoBack?: boolean;
  /** Función de retry personalizada */
  onRetry?: () => void;
  /** Función de navegación hacia atrás personalizada */
  onGoBack?: () => void;
  /** Función de reporte de errores */
  onReportError?: (error: Error, errorInfo: ErrorInfo) => void;
  /** Clase CSS adicional para el contenedor de error */
  className?: string;
  /** Nivel de logging */
  logLevel?: 'none' | 'console' | 'service';
}

class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  private retryTimeoutId: number | null = null;

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

  static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {
    return {
      hasError: true,
      error,
    };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    this.setState({
      error,
      errorInfo,
    });

    // Log del error
    this.logError(error, errorInfo);

    // Callback opcional para manejo de errores
    if (this.props.onError) {
      this.props.onError(error, errorInfo);
    }
  }

  private logError = (error: Error, errorInfo: ErrorInfo) => {
    const { logLevel = 'console' } = this.props;

    if (logLevel === 'none') return;

    const errorData = {
      message: error.message,
      stack: error.stack,
      componentStack: errorInfo.componentStack,
      timestamp: new Date().toISOString(),
      userAgent: navigator.userAgent,
      url: window.location.href,
    };

    if (logLevel === 'console' || process.env.NODE_ENV === 'development') {
      console.group('🚨 Error Boundary');
      console.error('Error:', error);
      console.error('Error Info:', errorInfo);
      console.error('Error Data:', errorData);
      console.groupEnd();
    }

    // Aquí se podría integrar con un servicio de logging como Sentry
    if (logLevel === 'service' && process.env.NODE_ENV === 'production') {
      // Ejemplo: Sentry.captureException(error, { extra: errorData });
    }
  };

  private handleRetry = () => {
    if (this.props.onRetry) {
      this.props.onRetry();
    } else {
      this.setState({
        hasError: false,
        error: null,
        errorInfo: null,
      });
    }
  };

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

  private handleGoBack = () => {
    if (this.props.onGoBack) {
      this.props.onGoBack();
    } else if (window.history.length > 1) {
      window.history.back();
    } else {
      window.location.href = '/';
    }
  };

  private handleReportError = () => {
    const { error, errorInfo } = this.state;
    if (error && errorInfo && this.props.onReportError) {
      this.props.onReportError(error, errorInfo);
    }
  };

  componentWillUnmount() {
    if (this.retryTimeoutId) {
      window.clearTimeout(this.retryTimeoutId);
    }
  }

  render() {
    const { hasError, error, errorInfo } = this.state;
    const {
      children,
      fallback,
      title = 'Oops! Algo salió mal',
      description = 'Ha ocurrido un error inesperado en la aplicación. Nuestro equipo ha sido notificado.',
      showDetails = process.env.NODE_ENV === 'development',
      enableRetry = true,
      enableReload = true,
      enableGoBack = true,
      className,
    } = this.props;

    if (!hasError) {
      return children;
    }

    // Si hay un componente de fallback personalizado
    if (fallback && error && errorInfo) {
      return fallback(error, errorInfo, this.handleRetry);
    }

    // UI de error por defecto
    return (
      <div 
        className={clsx(
          'min-h-[400px] flex items-center justify-center p-6',
          className
        )}
        role="alert"
        aria-live="assertive"
      >
        <div className="max-w-md w-full text-center">
          {/* Icono de error */}
          <div className="mb-6">
            <svg 
              className="w-20 h-20 text-color-error mx-auto" 
              fill="none" 
              stroke="currentColor" 
              viewBox="0 0 24 24"
              aria-hidden="true"
            >
              <path 
                strokeLinecap="round" 
                strokeLinejoin="round" 
                strokeWidth={1.5} 
                d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" 
              />
            </svg>
          </div>

          {/* Título */}
          <h2 className="text-2xl font-semibold text-text-primary mb-4">
            {title}
          </h2>

          {/* Descripción */}
          <p className="text-text-secondary mb-6 leading-relaxed">
            {description}
          </p>

          {/* Detalles del error (solo en desarrollo) */}
          {showDetails && error && (
            <details className="mb-6 text-left bg-bg-tertiary rounded-lg p-4">
              <summary className="cursor-pointer font-medium text-color-error mb-2">
                Detalles técnicos
              </summary>
              <div className="space-y-2 text-sm text-text-secondary font-mono">
                <div>
                  <strong>Error:</strong> {error.message}
                </div>
                {error.stack && (
                  <div>
                    <strong>Stack:</strong>
                    <pre className="mt-1 overflow-auto max-h-40 bg-bg-quaternary p-2 rounded text-xs">
                      {error.stack}
                    </pre>
                  </div>
                )}
                {errorInfo?.componentStack && (
                  <div>
                    <strong>Component Stack:</strong>
                    <pre className="mt-1 overflow-auto max-h-40 bg-bg-quaternary p-2 rounded text-xs">
                      {errorInfo.componentStack}
                    </pre>
                  </div>
                )}
              </div>
            </details>
          )}

          {/* Acciones */}
          <div className="flex flex-col sm:flex-row gap-3 justify-center">
            {enableRetry && (
              <Button
                variant="primary"
                onClick={this.handleRetry}
                leftIcon={
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                  </svg>
                }
              >
                Reintentar
              </Button>
            )}

            {enableReload && (
              <Button
                variant="outline"
                onClick={this.handleReload}
                leftIcon={
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                  </svg>
                }
              >
                Recargar página
              </Button>
            )}

            {enableGoBack && (
              <Button
                variant="ghost"
                onClick={this.handleGoBack}
                leftIcon={
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
                  </svg>
                }
              >
                Volver atrás
              </Button>
            )}
          </div>

          {/* Reportar error */}
          {this.props.onReportError && (
            <div className="mt-6 pt-6 border-t border-border-primary">
              <Button
                variant="ghost"
                size="sm"
                onClick={this.handleReportError}
                className="text-text-tertiary hover:text-text-secondary"
              >
                📋 Reportar este error
              </Button>
            </div>
          )}
        </div>
      </div>
    );
  }
}

export default ErrorBoundary;