'use client';

import Link from 'next/link';
import { useParams } from 'next/navigation';
import { useQuery } from '@tanstack/react-query';
import { format } from 'date-fns';
import { Copy, Wrench } from 'lucide-react';
import { toast } from 'sonner';

import type { Route } from 'next';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { ERROR_CODES, isErrorCode } from '@/lib/error-codes';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import { apiFetch } from '@/lib/api/client';
import { useBreadcrumbHint } from '@/hooks/use-breadcrumb-hint';
import type { ErrorEvent } from '@/lib/db/schema/system';
import type { LikelyCulprit } from '@/lib/error-classifier';

interface DetailResponse {
  data: ErrorEvent & { likelyCulprit: LikelyCulprit | null };
}

/**
 * Detail view for a single captured error. Shows everything an admin
 * needs to triage:
 *
 *  - Request shape: method, path, status, duration, who fired it
 *  - Error: name, message, full stack head, (sanitized) request body
 *  - Likely-culprit hint: heuristic-driven plain-English root-cause
 *  - Raw metadata: pg SQLSTATE codes, internal-message debug strings
 */
export default function ErrorEventDetailPage() {
  const params = useParams<{ portSlug: string; requestId: string }>();
  const portSlug = params?.portSlug ?? '';
  const requestId = params?.requestId ?? '';

  // Smart-back target: send the user back to the error list, not the
  // generic Administration page that URL-derivation would land on.
  useBreadcrumbHint(
    portSlug
      ? {
          parents: [{ label: 'Error inspector', href: `/${portSlug}/admin/errors` }],
          current: `Error ${requestId.slice(0, 8)}…`,
        }
      : null,
  );

  const query = useQuery<DetailResponse>({
    queryKey: ['admin', 'error-events', requestId],
    queryFn: () => apiFetch<DetailResponse>(`/api/v1/admin/error-events/${requestId}`),
    enabled: Boolean(requestId),
  });

  function copy(text: string, label: string) {
    if (typeof navigator === 'undefined' || !navigator.clipboard) return;
    void navigator.clipboard.writeText(text);
    toast.success(`${label} copied`);
  }

  if (query.isLoading) {
    return (
      <div className="space-y-3">
        <Skeleton className="h-8 w-48" />
        <Skeleton className="h-32 w-full" />
        <Skeleton className="h-64 w-full" />
      </div>
    );
  }

  const event = query.data?.data;
  if (!event) {
    return (
      <Card>
        <CardContent className="py-12 text-center text-sm text-muted-foreground">
          Error event not found. It may have been pruned or you may not have access.
        </CardContent>
      </Card>
    );
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2 flex-wrap">
        <h1 className="text-2xl font-bold">Error {requestId.slice(0, 8)}…</h1>
        <Badge
          variant="outline"
          className={
            event.statusCode >= 500
              ? 'border-destructive/40 text-destructive'
              : 'border-amber-300 text-amber-800'
          }
        >
          {event.statusCode}
        </Badge>
        {event.likelyCulprit && (
          <Badge variant="secondary" className="gap-1">
            <Wrench className="h-3 w-3" />
            {event.likelyCulprit.label}
          </Badge>
        )}
        <Button size="sm" variant="ghost" onClick={() => copy(requestId, 'Reference ID')}>
          <Copy className="mr-1.5 h-3 w-3" />
          Copy ID
        </Button>
      </div>

      {event.likelyCulprit && (
        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium flex items-center gap-2">
              <Wrench className="h-4 w-4" /> Likely culprit
            </CardTitle>
          </CardHeader>
          <CardContent className="text-sm">
            <p className="font-medium">{event.likelyCulprit.label}</p>
            <p className="text-muted-foreground mt-1">{event.likelyCulprit.hint}</p>
            <p className="text-xs text-muted-foreground mt-2">
              Subsystem: <code className="font-mono">{event.likelyCulprit.subsystem}</code>
            </p>
          </CardContent>
        </Card>
      )}

      {/* If the captured error has a registered code on its metadata,
       *  surface the canonical user-facing message + status from the
       *  registry so the admin can compare what the user saw to what
       *  the system actually did. */}
      {(() => {
        const meta = (event.metadata ?? {}) as Record<string, unknown>;
        const code = typeof meta.code === 'string' ? meta.code : null;
        if (!code || !isErrorCode(code)) return null;
        const def = ERROR_CODES[code];
        return (
          <Card>
            <CardHeader>
              <CardTitle className="text-sm font-medium">Error code</CardTitle>
            </CardHeader>
            <CardContent className="space-y-1 text-sm">
              <div className="flex items-center gap-2">
                <Badge variant="outline">{def.status}</Badge>
                <code className="font-mono text-xs font-semibold">{code}</code>
              </div>
              <p className="mt-2">{def.userMessage}</p>
              <p className="text-xs text-muted-foreground">
                Compare to the message the user saw in their toast.{' '}
                <Link
                  href={`/${portSlug}/admin/errors/codes` as Route}
                  className="text-primary hover:underline"
                >
                  All codes →
                </Link>
              </p>
            </CardContent>
          </Card>
        );
      })()}

      <Card>
        <CardHeader>
          <CardTitle className="text-sm font-medium">Request</CardTitle>
        </CardHeader>
        <CardContent className="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
          <KV label="Method" value={event.method} />
          <KV label="Path" value={event.path} mono />
          <KV label="When" value={format(new Date(event.createdAt), 'PPpp')} />
          <KV label="Duration" value={event.durationMs ? `${event.durationMs} ms` : '-'} />
          <KV label="Port" value={event.portId ?? '(none)'} mono />
          <KV label="User" value={event.userId ?? '(none)'} mono />
          <KV label="IP" value={event.ipAddress ?? '-'} mono />
          <KV label="User agent" value={event.userAgent ?? '-'} />
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle className="text-sm font-medium">Error</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3 text-sm">
          <KV label="Name" value={event.errorName ?? '-'} mono />
          <div>
            <p className="text-xs text-muted-foreground">Message</p>
            <p className="mt-0.5 font-mono whitespace-pre-wrap wrap-break-word">
              {event.errorMessage ?? '-'}
            </p>
          </div>
          {event.errorStack && (
            <div>
              <div className="flex items-center justify-between">
                <p className="text-xs text-muted-foreground">Stack (truncated)</p>
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => copy(event.errorStack ?? '', 'Stack')}
                >
                  <Copy className="mr-1.5 h-3 w-3" /> Copy
                </Button>
              </div>
              <pre className="mt-1 max-h-96 overflow-auto rounded bg-muted p-2 text-xs font-mono whitespace-pre-wrap wrap-break-word">
                {event.errorStack}
              </pre>
            </div>
          )}
        </CardContent>
      </Card>

      {event.requestBodyExcerpt && (
        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">
              Request body (sanitized, max 1 KB)
            </CardTitle>
          </CardHeader>
          <CardContent>
            <pre className="max-h-64 overflow-auto rounded bg-muted p-2 text-xs font-mono whitespace-pre-wrap wrap-break-word">
              {event.requestBodyExcerpt}
            </pre>
          </CardContent>
        </Card>
      )}

      {event.metadata !== null &&
        typeof event.metadata === 'object' &&
        Object.keys(event.metadata as Record<string, unknown>).length > 0 && (
          <Card>
            <CardHeader>
              <CardTitle className="text-sm font-medium">Metadata</CardTitle>
            </CardHeader>
            <CardContent>
              <pre className="overflow-auto rounded bg-muted p-2 text-xs font-mono">
                {JSON.stringify(event.metadata, null, 2)}
              </pre>
            </CardContent>
          </Card>
        )}
    </div>
  );
}

function KV({ label, value, mono }: { label: string; value: string | null; mono?: boolean }) {
  return (
    <div>
      <p className="text-xs text-muted-foreground">{label}</p>
      <p className={`mt-0.5 ${mono ? 'font-mono text-xs' : ''}`}>{value ?? '-'}</p>
    </div>
  );
}
