
import { AlertTriangle, Archive, MoreHorizontal, RefreshCw, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

import { useEffect, useRef, useState } from 'react';

import { Head, Link, router } from '@inertiajs/react';

import { AdminDataTable } from '@/Components/admin/AdminDataTable';
import { SortHeader } from '@/Components/admin/SortHeader';
import PageHeader from '@/Components/layout/PageHeader';
import { Alert, AlertTitle } from '@/Components/ui/alert';
import { Badge } from '@/Components/ui/badge';
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from '@/Components/ui/breadcrumb';
import { Button } from '@/Components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/Components/ui/card';
import { Checkbox } from '@/Components/ui/checkbox';
import { ConfirmDialog } from '@/Components/ui/confirm-dialog';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/Components/ui/dropdown-menu';
import { Input } from '@/Components/ui/input';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/Components/ui/table';
import { useAdminFilters } from '@/hooks/useAdminFilters';
import { useAdminKeyboardShortcuts } from '@/hooks/useAdminKeyboardShortcuts';
import { useNavigationState } from '@/hooks/useNavigationState';
import AdminLayout from '@/Layouts/AdminLayout';
import { formatRelativeTime } from '@/lib/format';
import type { PaginatedResponse } from '@/types';

interface DlqJob {
  id: number;
  job_class: string;
  queue: string;
  error_message: string;
  attempts_exhausted: number;
  retryable: boolean;
  replayed_at: string | null;
  created_at: string;
}

interface DlqStats {
  total: number;
  retryable: number;
  pending_replay: number;
  replayed: number;
}

interface Props {
  jobs: PaginatedResponse<DlqJob>;
  filters: {
    retryable?: string;
    replayed?: string;
    job_class?: string;
    sort?: string;
    dir?: string;
  };
  stats: DlqStats;
}

function shortClass(jobClass: string): string {
  const parts = jobClass.split('\\');
  return parts[parts.length - 1] ?? jobClass;
}

export default function AdminDlqIndex({ jobs, filters, stats }: Props) {
  const [selected, setSelected] = useState<number[]>([]);
  const [replayingId, setReplayingId] = useState<number | null>(null);
  const [deletingId, setDeletingId] = useState<number | null>(null);
  const [bulkAction, setBulkAction] = useState<'replay' | 'delete' | null>(null);
  const [purgeOpen, setPurgeOpen] = useState(false);
  const [purgeDays, setPurgeDays] = useState(30);
  const filterDebounceRef = useRef<ReturnType<typeof setTimeout>>();
  useEffect(() => () => clearTimeout(filterDebounceRef.current), []);

  const { handleSort, handlePage } = useAdminFilters({
    route: '/admin/dlq',
    filters: filters ?? {},
    routerOptions: { preserveScroll: true },
  });
  const isNavigating = useNavigationState();

  useAdminKeyboardShortcuts({
    onSearch: () => {
      document.querySelector<HTMLInputElement>('[data-search-input]')?.focus();
    },
    onNextPage:
      jobs.current_page < jobs.last_page ? () => handlePage(jobs.current_page + 1) : undefined,
    onPrevPage:
      jobs.current_page > 1 ? () => handlePage(jobs.current_page - 1) : undefined,
  });

  const toggleSelect = (id: number) => {
    setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]));
  };

  const toggleAll = () => {
    setSelected((prev) => (prev.length === jobs.data.length ? [] : jobs.data.map((j) => j.id)));
  };

  const handleReplay = (job: DlqJob) => {
    router.post(`/admin/dlq/${job.id}/replay`, {}, { onFinish: () => setReplayingId(null) });
  };

  const handleDelete = (job: DlqJob) => {
    router.delete(`/admin/dlq/${job.id}`, {
      onFinish: () => setDeletingId(null),
    });
  };

  const handleBulkReplay = () => {
    const count = selected.length;
    router.post(
      '/admin/dlq/bulk-replay',
      { ids: selected },
      {
        onSuccess: () => {
          toast.success(`${count} job(s) queued for replay.`);
          setBulkAction(null);
          setSelected([]);
        },
        onError: () => {
          toast.error('Operation failed. Your session may have expired — refresh and try again.');
          setBulkAction(null);
          setSelected([]);
        },
      },
    );
  };

  const handleBulkDelete = () => {
    const count = selected.length;
    router.delete('/admin/dlq', {
      data: { ids: selected },
      onSuccess: () => {
        toast.success(`${count} job(s) deleted.`);
        setBulkAction(null);
        setSelected([]);
      },
      onError: () => {
        toast.error('Operation failed. Your session may have expired — please refresh and try again.');
        setBulkAction(null);
        setSelected([]);
      },
    });
  };

  return (
    <AdminLayout>
      <Head title="Admin - Dead Letter Queue" />

      <div className="container py-6 space-y-6">
        <Breadcrumb>
          <BreadcrumbList>
            <BreadcrumbItem>
              <BreadcrumbLink asChild>
                <Link href="/admin">Admin</Link>
              </BreadcrumbLink>
            </BreadcrumbItem>
            <BreadcrumbSeparator />
            <BreadcrumbItem>
              <BreadcrumbPage>Dead Letter Queue</BreadcrumbPage>
            </BreadcrumbItem>
          </BreadcrumbList>
        </Breadcrumb>

        <PageHeader
          title="Dead Letter Queue"
          description="Jobs that exhausted all retry attempts"
        />

        {stats.retryable > 10 && (
          <Alert variant="destructive">
            <AlertTriangle className="h-4 w-4" />
            <AlertTitle>{stats.retryable} retryable jobs in dead letter queue</AlertTitle>
          </Alert>
        )}

        {/* Stats */}
        <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
          {[
            { label: 'Total', value: stats.total },
            { label: 'Retryable', value: stats.retryable },
            { label: 'Pending Replay', value: stats.pending_replay },
            { label: 'Replayed', value: stats.replayed },
          ].map(({ label, value }) => (
            <Card key={label}>
              <CardContent className="pt-4">
                <p className="text-2xl font-bold">{value}</p>
                <p className="text-sm text-muted-foreground">{label}</p>
              </CardContent>
            </Card>
          ))}
        </div>

        {/* Purge */}
        <Card>
          <CardHeader>
            <CardTitle className="text-sm font-medium">Purge Old Jobs</CardTitle>
            <CardDescription>Permanently delete dead letter jobs older than a specified number of days.</CardDescription>
          </CardHeader>
          <CardContent>
            <div className="flex items-center gap-3">
              <Input
                type="number"
                min={1}
                max={365}
                value={purgeDays}
                onChange={(e) => setPurgeDays(Math.max(1, Math.min(365, parseInt(e.target.value, 10) || 30)))}
                className="w-24"
                aria-label="Purge days"
              />
              <span className="text-sm text-muted-foreground">days old</span>
              <Button variant="destructive" size="sm" onClick={() => setPurgeOpen(true)}>
                <Trash2 className="h-4 w-4 mr-1" />
                Purge
              </Button>
            </div>
          </CardContent>
        </Card>

        {/* Jobs list */}
        <div className="space-y-4">
          <div>
            <h3 className="text-lg font-semibold">Jobs</h3>
            <p className="text-sm text-muted-foreground">Exhausted jobs captured for review and replay</p>
          </div>

          <div className="flex gap-2 flex-wrap">
            <Input
              data-search-input
              placeholder="Filter by job class..."
              defaultValue={filters.job_class ?? ''}
              className="w-64"
              aria-label="Filter by job class"
              onChange={(e) => {
                const value = e.target.value;
                clearTimeout(filterDebounceRef.current);
                filterDebounceRef.current = setTimeout(() => {
                  router.get(
                    '/admin/dlq',
                    { ...filters, job_class: value },
                    {
                      preserveState: true,
                      replace: true,
                    },
                  );
                }, 300);
              }}
            />
            {selected.length > 0 && (
              <div
                className="flex gap-2 ml-auto items-center"
                role="status"
                aria-live="polite"
              >
                <span className="text-xs text-muted-foreground">
                  {selected.length} of {jobs.data.length} on this page selected
                </span>
                <Button variant="outline" size="sm" onClick={() => setBulkAction('replay')}>
                  <RefreshCw className="h-4 w-4 mr-1" />
                  Replay ({selected.length})
                </Button>
                <Button variant="destructive" size="sm" onClick={() => setBulkAction('delete')}>
                  <Trash2 className="h-4 w-4 mr-1" />
                  Delete ({selected.length})
                </Button>
              </div>
            )}
          </div>

          <AdminDataTable
            isEmpty={jobs.data.length === 0}
            isNavigating={isNavigating}
            pagination={jobs}
            onPage={handlePage}
            paginationLabel="jobs"
            emptyIcon={Archive}
            emptyTitle="No dead letter jobs"
            emptyDescription="Jobs that exhaust all retry attempts will appear here."
          >
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-10">
                    <Checkbox
                      checked={selected.length === jobs.data.length && jobs.data.length > 0}
                      onCheckedChange={toggleAll}
                      aria-label="Select all on this page"
                    />
                  </TableHead>
                  <SortHeader
                    column="job_class"
                    label="Job"
                    currentSort={filters.sort}
                    currentDir={filters.dir}
                    onSort={handleSort}
                  />
                  <TableHead>Queue</TableHead>
                  <TableHead>Error</TableHead>
                  <SortHeader
                    column="attempts_exhausted"
                    label="Attempts"
                    currentSort={filters.sort}
                    currentDir={filters.dir}
                    onSort={handleSort}
                  />
                  <TableHead>Status</TableHead>
                  <SortHeader
                    column="created_at"
                    label="Age"
                    currentSort={filters.sort}
                    currentDir={filters.dir}
                    onSort={handleSort}
                  />
                  <TableHead className="text-right">Actions</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {jobs.data.map((job) => (
                  <TableRow key={job.id}>
                    <TableCell>
                      <Checkbox
                        checked={selected.includes(job.id)}
                        onCheckedChange={() => toggleSelect(job.id)}
                        aria-label={`Select ${shortClass(job.job_class)}`}
                      />
                    </TableCell>
                    <TableCell className="max-w-xs">
                      <span
                        className="font-mono text-xs font-medium truncate block"
                        title={job.job_class}
                      >
                        {shortClass(job.job_class)}
                      </span>
                    </TableCell>
                    <TableCell>
                      <Badge variant="outline">{job.queue}</Badge>
                    </TableCell>
                    <TableCell className="max-w-xs">
                      <span
                        className="text-xs text-muted-foreground line-clamp-2"
                        title={job.error_message}
                      >
                        {job.error_message}
                      </span>
                    </TableCell>
                    <TableCell className="text-center">{job.attempts_exhausted}</TableCell>
                    <TableCell>
                      {job.replayed_at ? (
                        <Badge variant="secondary">Replayed</Badge>
                      ) : job.retryable ? (
                        <Badge variant="warning">Retryable</Badge>
                      ) : (
                        <Badge variant="destructive">Non-retryable</Badge>
                      )}
                    </TableCell>
                    <TableCell>
                      <span className="text-xs text-muted-foreground">
                        {formatRelativeTime(job.created_at)}
                      </span>
                    </TableCell>
                    <TableCell className="text-right">
                      <DropdownMenu>
                        <DropdownMenuTrigger asChild>
                          <Button
                            variant="ghost"
                            size="sm"
                            aria-label={`Actions for ${shortClass(job.job_class)}`}
                          >
                            <MoreHorizontal className="h-4 w-4" />
                          </Button>
                        </DropdownMenuTrigger>
                        <DropdownMenuContent align="end">
                          {job.retryable && !job.replayed_at && (
                            <DropdownMenuItem onClick={() => setReplayingId(job.id)}>
                              <RefreshCw className="h-4 w-4 mr-2" />
                              Replay
                            </DropdownMenuItem>
                          )}
                          <DropdownMenuItem
                            onClick={() => setDeletingId(job.id)}
                            className="text-destructive"
                          >
                            <Trash2 className="h-4 w-4 mr-2" />
                            Delete
                          </DropdownMenuItem>
                        </DropdownMenuContent>
                      </DropdownMenu>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </AdminDataTable>
        </div>
      </div>

      {/* Single replay confirm */}
      <ConfirmDialog
        open={replayingId !== null}
        onOpenChange={(open) => {
          if (!open) setReplayingId(null);
        }}
        title="Replay job"
        description="Re-queue this job for execution. It will be dispatched to its original queue."
        confirmLabel="Replay"
        onConfirm={() => {
          const job = jobs.data.find((j) => j.id === replayingId);
          if (job) handleReplay(job);
        }}
      />

      {/* Single delete confirm */}
      <ConfirmDialog
        open={deletingId !== null}
        onOpenChange={(open) => {
          if (!open) setDeletingId(null);
        }}
        title="Delete dead letter job"
        description="This cannot be undone. The job record will be permanently removed."
        confirmLabel="Delete"
        variant="destructive"
        onConfirm={() => {
          const job = jobs.data.find((j) => j.id === deletingId);
          if (job) handleDelete(job);
        }}
      />

      {/* Bulk replay confirm */}
      <ConfirmDialog
        open={bulkAction === 'replay'}
        onOpenChange={(open) => {
          if (!open) setBulkAction(null);
        }}
        title={`Replay ${selected.length} jobs`}
        description="Re-queue all selected retryable jobs. Non-retryable jobs will be skipped."
        confirmLabel="Replay All"
        onConfirm={handleBulkReplay}
      />

      {/* Bulk delete confirm */}
      <ConfirmDialog
        open={bulkAction === 'delete'}
        onOpenChange={(open) => {
          if (!open) setBulkAction(null);
        }}
        title={`Delete ${selected.length} jobs`}
        description="Permanently delete all selected dead letter jobs. This cannot be undone."
        confirmLabel="Delete All"
        variant="destructive"
        onConfirm={handleBulkDelete}
      />

      {/* Purge confirm */}
      <ConfirmDialog
        open={purgeOpen}
        onOpenChange={(open) => {
          if (!open) setPurgeOpen(false);
        }}
        title="Purge dead letter jobs?"
        description={`This will permanently delete all DLQ entries older than ${purgeDays} days. This cannot be undone.`}
        confirmLabel="Purge"
        variant="destructive"
        onConfirm={() => {
          router.post('/admin/dlq/purge', { days: purgeDays }, { onFinish: () => setPurgeOpen(false) });
        }}
      />
    </AdminLayout>
  );
}
