"use client"

import * as React from "react"
import { ErrorState } from "../states/ErrorState"

interface ApiErrorBoundaryState {
  hasError: boolean
  error: Error | null
}

interface ApiErrorBoundaryProps {
  children: React.ReactNode
  /** Custom fallback to render on error. Receives error and reset function. */
  fallback?: (props: { error: Error; reset: () => void }) => React.ReactNode
  /** Called when the error boundary catches an error. */
  onError?: (error: Error, info: React.ErrorInfo) => void
}

/**
 * Error boundary for API-driven page content.
 *
 * Catches unhandled errors from children and renders ErrorState with a retry button.
 *
 * @example
 * <ApiErrorBoundary>
 *   <InvestorsTable />
 * </ApiErrorBoundary>
 */
export class ApiErrorBoundary extends React.Component<
  ApiErrorBoundaryProps,
  ApiErrorBoundaryState
> {
  constructor(props: ApiErrorBoundaryProps) {
    super(props)
    this.state = { hasError: false, error: null }
  }

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

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    this.props.onError?.(error, info)
  }

  reset = () => {
    this.setState({ hasError: false, error: null })
  }

  render() {
    if (this.state.hasError && this.state.error) {
      if (this.props.fallback) {
        return this.props.fallback({ error: this.state.error, reset: this.reset })
      }
      return (
        <ErrorState
          message={this.state.error.message || "An unexpected error occurred"}
          onRetry={this.reset}
        />
      )
    }
    return this.props.children
  }
}
