import React, { type ReactNode } from 'react';
import { AlertTriangle, RefreshCw } from 'lucide-react';
import { Button } from '@/components/ui/button';

// ────────────────────────────────────────────────────────────────────────────
// ErrorBoundary Component
// ────────────────────────────────────────────────────────────────────────────
interface ErrorBoundaryProps {
  children?: ReactNode;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
  componentStack: string | null;
}

class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false, error: null, componentStack: null };
  }

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

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

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

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

  render() {
    if (!this.state.hasError) {
      return this.props.children;
    }

    const { error, componentStack } = this.state;

    return (
      <div className="min-h-screen bg-background flex items-center justify-center p-4">
        <div className="max-w-2xl w-full rounded-xl border border-destructive/20 bg-destructive/5 px-6 py-8 text-center">
          <div className="mx-auto mb-6 h-16 w-16 rounded-full bg-destructive text-destructive-foreground flex items-center justify-center">
            <AlertTriangle className="h-8 w-8" />
          </div>

          <h1 className="text-2xl font-bold tracking-tight text-foreground mb-2">
            Something went wrong
          </h1>

          <p className="text-sm text-muted-foreground mb-6">
            An unexpected error occurred. You can try to recover by reloading the page or resetting this component.
          </p>

          {error && (
            <div className="mb-6 rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-left">
              <p className="text-xs font-semibold uppercase tracking-wider text-destructive mb-2">
                Error Message
              </p>
              <pre className="text-xs text-destructive-foreground font-mono overflow-auto max-h-32">
                {String(error)}
              </pre>
            </div>
          )}

          {componentStack && (
            <div className="mb-6 rounded-lg border border-destructive/20 bg-destructive/5 p-4">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-destructive/70 mb-2">
                Component Stack (for debugging)
              </p>
              <pre className="text-[10px] text-destructive-foreground/60 font-mono overflow-auto max-h-24">
                {componentStack}
              </pre>
            </div>
          )}

          <div className="flex flex-wrap items-center justify-center gap-3">
            <Button
              variant="default"
              onClick={this.handleReset}
              className="flex items-center gap-2 text-xs"
            >
              <RefreshCw className="h-3 w-3" />
              Try Again
            </Button>
            <Button
              variant="outline"
              onClick={this.handleReload}
              className="flex items-center gap-2 text-xs border-destructive/30 hover:bg-destructive/10 hover:text-destructive hover:border-destructive/50"
            >
              Reload Page
            </Button>
          </div>
        </div>
      </div>
    );
  }
}

// ────────────────────────────────────────────────────────────────────────────
// withErrorBoundary HOC
// ────────────────────────────────────────────────────────────────────────────
export function withErrorBoundary<P extends object>(
  Component: React.ComponentType<P>,
  displayName: string = Component.displayName || Component.name || 'Component',
) {
  function WrappedComponent(props: P) {
    return (
      <ErrorBoundary>
        <Component {...props} />
      </ErrorBoundary>
    );
  }

  WrappedComponent.displayName = `withErrorBoundary(${displayName})`;
  return WrappedComponent;
}

export default ErrorBoundary;
