import './ErrorBoundary.css';
import { Component, type ErrorInfo, type ReactNode } from 'react';

interface ErrorBoundaryProps {
  children: ReactNode;
  /** Rendu de repli optionnel ; sinon, fallback par défaut avec « Réessayer ». */
  fallback?: (error: Error, reset: () => void) => ReactNode;
}

interface ErrorBoundaryState {
  error: Error | null;
}

/**
 * Capture les erreurs de rendu des composants enfants et affiche un repli au
 * lieu d'un écran blanc. À monter haut dans l'arbre (ex. autour de l'`Outlet`
 * dans Layout). Ne capture PAS les erreurs asynchrones (gérées par `useAsync`).
 */
export default class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  state: ErrorBoundaryState = { error: null };

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

  componentDidCatch(error: Error, info: ErrorInfo) {
    console.error('ErrorBoundary a capturé une erreur :', error, info);
  }

  private 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="error-boundary" role="alert">
        <h2 className="error-boundary__title">Une erreur est survenue</h2>
        <p className="error-boundary__message">{error.message}</p>
        <button className="btn-primary" onClick={this.reset}>
          Réessayer
        </button>
      </div>
    );
  }
}
