import { Component, type ErrorInfo, type ReactNode } from 'react'

import { Button } from '@/components/ui'

interface State {
  error: Error | null
}

/**
 * Last line of defence against a render error taking the whole app to a blank
 * page. A visitor mid-purchase deserves a recoverable screen and a route out,
 * not white space.
 */
export class ErrorBoundary extends Component<{ children: ReactNode }, State> {
  override state: State = { error: null }

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

  override componentDidCatch(error: Error, info: ErrorInfo): void {
    // A real deployment would forward this to an error tracker.
    console.error('Unhandled render error', error, info.componentStack)
  }

  override render(): ReactNode {
    if (this.state.error === null) {
      return this.props.children
    }

    return (
      <div className="flex min-h-dvh items-center justify-center bg-canvas px-4">
        <div className="w-full max-w-md text-center">
          <h1 className="text-xl font-semibold text-text-primary">Something went wrong</h1>
          <p className="mt-2 text-sm text-text-secondary">
            The page could not be displayed. Your account and any in-progress transaction are
            unaffected.
          </p>

          <div className="mt-6 flex justify-center gap-3">
            <Button variant="secondary" onClick={() => this.setState({ error: null })}>
              Try again
            </Button>
            <Button onClick={() => window.location.assign('/')}>Back to home</Button>
          </div>
        </div>
      </div>
    )
  }
}
