import { isRouteErrorResponse, useNavigate, useRouteError } from "react-router"
import { AlertTriangle, RefreshCw, Home } from "lucide-react"

import { AppShell } from "~/components/layout/app-shell"
import { Button } from "~/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card"

/**
 * Route-level error boundary.
 *
 * Re-export this as `ErrorBoundary` from any route and a crash in that route
 * degrades to a single explained card *inside the shell* — the nav, the theme
 * and every other screen stay reachable. The root boundary in `root.tsx` still
 * exists as the last resort, but it replaces the whole app with an unstyled
 * stack trace, which strands an operator mid-incident with no way out.
 *
 *     export { RouteErrorBoundary as ErrorBoundary } from "~/components/route-error"
 */
export function RouteErrorBoundary() {
  const error = useRouteError()
  const navigate = useNavigate()

  let title = "This screen hit an error"
  let description =
    "Something on this page failed to render. The rest of the console still works — you can retry, or head back to the overview."

  if (isRouteErrorResponse(error)) {
    if (error.status === 404) {
      title = "That page doesn't exist"
      description = "The link may be stale, or the screen may have been renamed."
    } else {
      title = `Request failed (${error.status})`
      description =
        error.statusText ||
        "The server rejected this request. Retry, and if it keeps failing check the service logs."
    }
  }

  // The message is useful to an operator even in prod — it's their own platform.
  // The stack is noise unless you're the one fixing it, so it stays in dev.
  const message = error instanceof Error ? error.message : null
  const stack =
    import.meta.env.DEV && error instanceof Error ? error.stack : undefined

  return (
    <AppShell>
      <Card>
        <CardHeader>
          <div className="flex items-start gap-3">
            <div className="flex size-10 shrink-0 items-center justify-center rounded-lg bg-destructive/10 text-destructive">
              <AlertTriangle className="size-5" />
            </div>
            <div className="min-w-0">
              <CardTitle>{title}</CardTitle>
              <CardDescription>{description}</CardDescription>
            </div>
          </div>
        </CardHeader>
        <CardContent className="flex flex-col gap-4">
          {message ? (
            <p className="rounded-md border bg-muted/30 px-3 py-2 font-mono text-xs text-muted-foreground">
              {message}
            </p>
          ) : null}

          <div className="flex flex-wrap items-center gap-2">
            <Button
              data-action="route-error-retry"
              onClick={() => window.location.reload()}
            >
              <RefreshCw className="size-4" />
              Retry
            </Button>
            <Button
              data-action="route-error-home"
              variant="outline"
              onClick={() => navigate("/")}
            >
              <Home className="size-4" />
              Back to overview
            </Button>
          </div>

          {stack ? (
            <details className="rounded-md border bg-muted/20 px-3 py-2 text-sm">
              <summary className="cursor-pointer text-muted-foreground">
                Stack trace (dev only)
              </summary>
              <pre className="mt-2 overflow-x-auto text-xs">
                <code>{stack}</code>
              </pre>
            </details>
          ) : null}
        </CardContent>
      </Card>
    </AppShell>
  )
}
