'use client';
import { Component, ErrorInfo, ReactNode } from 'react';
import { Stack, Typography } from '@mui/material';
import AppButton from './AppButton';
import AppIcon from './AppIcon';

export interface ErrorBoundaryProps {
  children: ReactNode;
  /** Diagnostic-only segment name (console log label) — never shown to the user. */
  name: string;
  /** Already-translated fallback copy — kept presentational/caller-owned (like every other shared
   * primitive in this kit) so this file never imports next-intl; it sits at the top of the `common`
   * barrel, so an eager i18n dependency here would drag `next-intl` into every test that imports
   * anything from `@/components`, mocked or not. */
  title: string;
  body: string;
  retryLabel: string;
}

interface State {
  hasError: boolean;
  error?: Error;
  errorInfo?: ErrorInfo;
}

/**
 * Error boundary wrapping a subtree of the app (a shell's content area). Renders a branded fallback with
 * a retry affordance (re-mounts the children by clearing `hasError`); the raw error + component stack are
 * **logged, never shown**, in production — only a development build renders the dev-only `<details>`
 * block.
 * @component ErrorBoundary
 */
class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    this.setState({ error, errorInfo });
    console.error(`[ErrorBoundary:${this.props.name}]`, error, errorInfo.componentStack);
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: undefined, errorInfo: undefined });
  };

  render() {
    if (this.state.hasError) {
      const { error, errorInfo } = this.state;
      return (
        <Stack sx={{ alignItems: 'center', justifyContent: 'center', gap: 1.5, py: 6, px: 2, textAlign: 'center' }}>
          <AppIcon icon="warning" size={36} color="var(--bal-warning)" />
          <Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
            {this.props.title}
          </Typography>
          <Typography variant="body2" sx={{ color: 'text.secondary', maxWidth: 360 }}>
            {this.props.body}
          </Typography>
          <AppButton color="primary" variant="outlined" onClick={this.handleRetry}>
            {this.props.retryLabel}
          </AppButton>
          {process.env.NODE_ENV !== 'production' && (error || errorInfo) ? (
            <Typography
              component="details"
              variant="caption"
              sx={{ color: 'text.secondary', maxWidth: 480, textAlign: 'start', whiteSpace: 'pre-wrap' }}
            >
              <Typography component="summary" variant="caption" sx={{ cursor: 'pointer' }}>
                Dev-only error detail
              </Typography>
              {error?.toString()}
              {'\n'}
              {errorInfo?.componentStack}
            </Typography>
          ) : null}
        </Stack>
      );
    }
    return this.props.children;
  }
}

export default ErrorBoundary;
