/**
 * 全局 React ErrorBoundary
 *
 * - 捕获子树渲染错误，避免白屏
 * - 自动上报到 error_logs（通过 reportError）
 * - 提供"重试"按钮：重置错误状态
 */

import { Component, ErrorInfo, ReactNode } from "react";
import { Button } from "@/components/ui/button";
import { AlertTriangle } from "lucide-react";
import { reportError } from "@/lib/errorReporter";

interface Props {
  children: ReactNode;
  /** 自定义降级 UI；不传则使用默认页面 */
  fallback?: (err: Error, reset: () => void) => ReactNode;
  /** 上报时附带的上下文标签，便于定位作用域 */
  scope?: string;
}

interface State {
  error: Error | null;
}

export class ErrorBoundary extends Component<Props, State> {
  state: State = { error: null };

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

  componentDidCatch(error: Error, info: ErrorInfo) {
    void reportError({
      message: error.message || "React render error",
      stack: error.stack,
      componentStack: info.componentStack ?? undefined,
      severity: "fatal",
      context: { scope: this.props.scope ?? "root", source: "ErrorBoundary" },
    });
  }

  reset = () => this.setState({ error: null });

  render() {
    const { error } = this.state;
    if (!error) return this.props.children;

    if (this.props.fallback) return this.props.fallback(error, this.reset);

    return (
      <div className="min-h-screen flex items-center justify-center bg-background p-6">
        <div className="max-w-md w-full text-center space-y-4">
          <div className="flex justify-center">
            <AlertTriangle className="h-12 w-12 text-destructive" />
          </div>
          <h1 className="text-xl font-semibold text-foreground">页面出了点问题</h1>
          <p className="text-sm text-muted-foreground break-words">
            {error.message || "未知错误，已自动记录，我们会尽快处理。"}
          </p>
          <div className="flex gap-2 justify-center pt-2">
            <Button variant="outline" onClick={() => window.location.reload()}>
              刷新页面
            </Button>
            <Button onClick={this.reset}>重试</Button>
          </div>
        </div>
      </div>
    );
  }
}
