import { Component } from "react";
import type { ErrorInfo, ReactNode } from "react";

interface ErrorBoundaryProps {
  children: ReactNode;
}

interface ErrorBoundaryState {
  error: Error | null;
}

/**
 * Top-level ErrorBoundary — renders the error visibly so the actual exception
 * appears in the DOM (and therefore in the Playwright snapshot) instead of
 * React 18+ unmounting the entire tree to a blank `<div id="root">`.
 *
 * Background: GRO-2094. The bundle was executing but never painting, with
 * the failure swallowed. Surfacing the error here is the first step; the
 * real fix is in the underlying component that threw.
 */
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  state: ErrorBoundaryState = { error: null };

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { error };
  }

  componentDidCatch(error: Error, info: ErrorInfo): void {
    // Also surface to the console — this is what the test harness greps for.
    // eslint-disable-next-line no-console
    console.error("[ErrorBoundary] Uncaught render error:", error, info);
  }

  render() {
    if (this.state.error) {
      const err = this.state.error;
      return (
        <div
          data-testid="error-boundary"
          style={{
            padding: "2rem",
            fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
            color: "#7f1d1d",
            background: "#fef2f2",
            minHeight: "100vh",
            boxSizing: "border-box",
          }}
        >
          <h1 style={{ fontSize: 18, margin: "0 0 0.5rem" }}>Something went wrong</h1>
          <p style={{ margin: "0 0 1rem", color: "#991b1b" }}>
            The app failed to render. The full error is shown below — please share this
            output when reporting the bug.
          </p>
          <pre
            data-testid="error-boundary-message"
            style={{
              whiteSpace: "pre-wrap",
              wordBreak: "break-word",
              background: "#fff",
              border: "1px solid #fecaca",
              borderRadius: 6,
              padding: "0.75rem 1rem",
              margin: 0,
              fontSize: 13,
              lineHeight: 1.4,
            }}
          >
            {err.name}: {err.message}
            {"\n\n"}
            {err.stack ?? "(no stack)"}
          </pre>
        </div>
      );
    }
    return this.props.children;
  }
}
