/**
 * Node Error Boundary
 *
 * Catches errors in individual nodes to prevent the entire canvas from crashing.
 */

import React, { Component, type ErrorInfo, type ReactNode } from 'react';
import { createDebug } from '../utils/debug';

const debug = createDebug('error-boundary');

export interface NodeErrorBoundaryProps {
    /** The node ID for error reporting */
    nodeId: string;
    /** Child content to render */
    children: ReactNode;
    /** Callback when an error occurs */
    onError?: (nodeId: string, error: Error, errorInfo: ErrorInfo) => void;
    /** Custom fallback UI renderer */
    renderFallback?: (props: { nodeId: string; error: Error; reset: () => void }) => ReactNode;
}

interface NodeErrorBoundaryState {
    hasError: boolean;
    error: Error | null;
}

/**
 * Default fallback UI for errored nodes
 */
function DefaultFallback({ nodeId, error, reset }: { nodeId: string; error: Error; reset: () => void }) {
    return (
        <div
            style={{
                padding: '16px',
                backgroundColor: 'rgba(239, 68, 68, 0.1)',
                border: '1px solid rgba(239, 68, 68, 0.3)',
                borderRadius: '8px',
                color: '#ef4444',
                fontSize: '12px',
                minWidth: '150px',
            }}
        >
            <div style={{ fontWeight: 600, marginBottom: '8px' }}>⚠️ Node Error</div>
            <div style={{ color: '#888', marginBottom: '8px', wordBreak: 'break-word' }}>
                {error.message || 'Unknown error'}
            </div>
            <button
                onClick={reset}
                style={{
                    padding: '4px 8px',
                    fontSize: '11px',
                    backgroundColor: 'rgba(239, 68, 68, 0.2)',
                    border: '1px solid rgba(239, 68, 68, 0.3)',
                    borderRadius: '4px',
                    color: '#ef4444',
                    cursor: 'pointer',
                }}
            >
                Retry
            </button>
        </div>
    );
}

/**
 * Error boundary component for individual nodes.
 * Catches rendering errors and displays a fallback UI.
 */
export class NodeErrorBoundary extends Component<NodeErrorBoundaryProps, NodeErrorBoundaryState> {
    constructor(props: NodeErrorBoundaryProps) {
        super(props);
        this.state = { hasError: false, error: null };
    }

    static getDerivedStateFromError(error: Error): NodeErrorBoundaryState {
        return { hasError: true, error };
    }

    componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
        const { nodeId, onError } = this.props;
        debug.error('Error in node %s: %O %O', nodeId, error, errorInfo);
        onError?.(nodeId, error, errorInfo);
    }

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

    render(): ReactNode {
        const { hasError, error } = this.state;
        const { nodeId, children, renderFallback } = this.props;

        if (hasError && error) {
            if (renderFallback) {
                return renderFallback({ nodeId, error, reset: this.reset });
            }
            return <DefaultFallback nodeId={nodeId} error={error} reset={this.reset} />;
        }

        return children;
    }
}
