/**
 * ErrorBoundary — 渲染错误边界
 *
 * 捕获子组件渲染时的同步异常，显示降级 UI 而非整个应用白屏。
 */

import { Component, type ReactNode } from 'react';
import { Box, Typography, Button } from '@mui/material';
import { AlertTriangle } from 'lucide-react';

interface Props {
  children: ReactNode;
  fallbackTitle?: string;
}

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

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

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

  componentDidCatch(error: Error, info: { componentStack: string }): void {
    // #49 修复: 上报错误到主进程，便于记录到 electron-log 与审计日志，集中排查
    // 主进程可注册 ipcMain.on('error:report', ...) 接收；未注册时 send 为静默失败，不影响兜底
    try {
      window.metona?.app?.reportError({
        type: 'react_error_boundary',
        error: error.message,
        stack: error.stack,
        componentStack: info.componentStack,
        timestamp: Date.now(),
      });
    } catch {
      // 上报失败不影响兜底逻辑
    }
    console.error('[ErrorBoundary]', error, info.componentStack);
  }

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

  render(): ReactNode {
    if (!this.state.hasError) return this.props.children;
    return (
      <Box sx={{ p: 2, display: 'flex', flexDirection: 'column', gap: 1, alignItems: 'center', justifyContent: 'center', height: '100%' }}>
        <AlertTriangle size={24} color="var(--mui-palette-error-main)" />
        <Typography variant="caption" sx={{ fontWeight: 600 }}>
          {this.props.fallbackTitle ?? '组件渲染失败'}
        </Typography>
        <Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 10, textAlign: 'center', wordBreak: 'break-word', maxWidth: '80%' }}>
          {this.state.error?.message ?? '未知错误'}
        </Typography>
        <Button size="small" variant="outlined" onClick={this.handleReset} sx={{ mt: 1, textTransform: 'none', fontSize: 11 }}>
          重试
        </Button>
      </Box>
    );
  }
}
