'use client'

import * as React from 'react'
import { cn } from '../../lib/utils'

export interface RouteError extends Error {
  digest?: string
}

export interface RouteErrorBoundaryProps {
  /** The error thrown during render — matches the Next.js `error.tsx` contract. */
  error: RouteError
  /** Re-render the route segment — matches the Next.js `error.tsx` contract. */
  reset: () => void
  /** Heading shown above the message. */
  title?: string
  /** Body copy shown in production (the raw error is only shown in development). */
  description?: string
  /** Label for the primary (retry) action. */
  retryLabel?: string
  /** Label for the secondary (home) action. Hidden when `homeHref` is null. */
  homeLabel?: string
  /** Destination for the secondary action. Pass `null` to hide it. Defaults to `/`. */
  homeHref?: string | null
  /**
   * Render-prop override for the entire surface. Receives the error plus the
   * resolved `reset`/`goHome` handlers so apps can fully brand the page while
   * keeping the Next.js wiring.
   */
  children?: (props: {
    error: RouteError
    reset: () => void
    goHome: () => void
  }) => React.ReactNode
  /** Called once on mount with the error — wire up your logger/Sentry here. */
  onError?: (error: RouteError) => void
  /** Override the outer wrapper className. */
  className?: string
}

/**
 * Route-level error surface for an app's `app/error.tsx`.
 *
 * Implements the Next.js App Router error contract (`{ error, reset }`) and
 * renders a neutral, brandable error card. Stack/digest details are only shown
 * in development. Use render-prop `children` for full custom UI.
 *
 * @example
 * // app/error.tsx
 * 'use client'
 * import { RouteErrorBoundary } from '@startsimpli/ui'
 * export default function Error(props: { error: Error & { digest?: string }; reset: () => void }) {
 *   return <RouteErrorBoundary {...props} />
 * }
 */
export function RouteErrorBoundary({
  error,
  reset,
  title = 'Something went wrong',
  description = 'We encountered an unexpected error. Please try again, or head back home if the problem persists.',
  retryLabel = 'Try again',
  homeLabel = 'Go home',
  homeHref = '/',
  children,
  onError,
  className,
}: RouteErrorBoundaryProps) {
  React.useEffect(() => {
    onError?.(error)
  }, [error, onError])

  const goHome = React.useCallback(() => {
    if (homeHref && typeof window !== 'undefined') {
      window.location.href = homeHref
    }
  }, [homeHref])

  if (children) {
    return <>{children({ error, reset, goHome })}</>
  }

  const isDevelopment = process.env.NODE_ENV === 'development'

  return (
    <div
      className={cn(
        'min-h-[60vh] flex items-center justify-center p-4',
        className
      )}
      role="alert"
      aria-live="assertive"
    >
      <div className="max-w-lg w-full rounded-xl border border-border bg-background p-8 shadow-sm text-center">
        <div
          className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-red-50"
          aria-hidden="true"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="32"
            height="32"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
            className="text-red-500"
          >
            <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" />
            <line x1="12" y1="9" x2="12" y2="13" />
            <line x1="12" y1="17" x2="12.01" y2="17" />
          </svg>
        </div>

        <h1 className="text-2xl font-semibold text-foreground mb-3">{title}</h1>
        <p className="text-sm text-muted-foreground mb-6 max-w-md mx-auto">
          {description}
        </p>

        {isDevelopment && (
          <div className="mb-6 rounded-lg border border-red-200 bg-red-50 p-4 text-left">
            <p className="mb-1 text-xs font-semibold text-red-800">
              Error (development only)
            </p>
            <p className="break-words font-mono text-sm text-red-700">
              {error.message}
            </p>
            {error.digest && (
              <p className="mt-2 font-mono text-xs text-red-700">
                Digest: {error.digest}
              </p>
            )}
            {error.stack && (
              <details className="mt-2">
                <summary className="cursor-pointer text-xs font-semibold text-red-800">
                  Stack trace
                </summary>
                <pre className="mt-2 max-h-64 overflow-auto whitespace-pre-wrap break-all rounded border border-red-200 bg-background p-3 text-xs">
                  {error.stack}
                </pre>
              </details>
            )}
          </div>
        )}

        {!isDevelopment && error.digest && (
          <p className="mb-6 text-xs text-muted-foreground">
            Reference:{' '}
            <code className="rounded bg-muted px-1.5 py-0.5 font-mono">
              {error.digest}
            </code>
          </p>
        )}

        <div className="flex flex-col gap-3 sm:flex-row sm:justify-center">
          <button
            onClick={reset}
            className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90"
          >
            {retryLabel}
          </button>
          {homeHref && (
            <button
              onClick={goHome}
              className="inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground"
            >
              {homeLabel}
            </button>
          )}
        </div>
      </div>
    </div>
  )
}
