"use client";

import { useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Trash2, RotateCcw, Bug } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Pagination } from "@/components/shared/pagination";
import { ConfirmDialog } from "@/components/shared/confirm-dialog";
import { EmptyState, ErrorState, TableSkeleton } from "@/components/shared/states";
import { forgetPushFailedJob, getPushFailedJobs, retryPushFailedJob } from "@/services/push";
import { queryKeys } from "@/lib/query-keys";
import { useUrlState } from "@/lib/use-url-state";
import { useI18n, useT } from "@/i18n";
import { formatRelative } from "@/lib/format";
import { friendlyErrorMessage } from "@/lib/errors";
import type { PushFailedJob } from "@/types/push";

export function FailedJobsTab() {
  const t = useT();
  const { locale } = useI18n();
  const queryClient = useQueryClient();
  const [page, setPage] = useUrlState("fj_page", 1, (value) => {
    const n = Number(value);
    return Number.isFinite(n) && n >= 1 ? n : null;
  });
  const [retrying, setRetrying] = useState<PushFailedJob | null>(null);
  const [forgetting, setForgetting] = useState<PushFailedJob | null>(null);

  const filters = useMemo(() => ({ page, rows: 10 }), [page]);
  const query = useQuery({
    queryKey: queryKeys.push.failedJobs(filters),
    queryFn: () => getPushFailedJobs(filters),
  });

  const retryMutation = useMutation({
    mutationFn: retryPushFailedJob,
    onSuccess: (response) => {
      toast.success(response.Message || t("push.failedJobRetried"));
      setRetrying(null);
      void queryClient.invalidateQueries({ queryKey: ["push", "failed-jobs"] });
      void queryClient.invalidateQueries({ queryKey: ["push", "deliveries"] });
      void queryClient.invalidateQueries({ queryKey: queryKeys.push.stats });
    },
    onError: (error) => {
      toast.error(friendlyErrorMessage(error, t));
    },
  });

  const forgetMutation = useMutation({
    mutationFn: forgetPushFailedJob,
    onSuccess: (response) => {
      toast.success(response.Message || t("push.failedJobForgotten"));
      setForgetting(null);
      void queryClient.invalidateQueries({ queryKey: ["push", "failed-jobs"] });
    },
    onError: (error) => {
      toast.error(friendlyErrorMessage(error, t));
    },
  });

  const jobs = query.data?.Model ?? [];

  return (
    <>
      <Card>
        {query.isPending ? (
          <TableSkeleton rows={8} cols={4} />
        ) : query.isError ? (
          <ErrorState message={friendlyErrorMessage(query.error, t)} onRetry={() => query.refetch()} />
        ) : jobs.length === 0 ? (
          <EmptyState title={t("push.emptyFailedJobs")} description={t("push.emptyFailedJobsHint")} icon={Bug} />
        ) : (
          <>
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("push.job")}</TableHead>
                    <TableHead>{t("push.queue")}</TableHead>
                    <TableHead>{t("push.failedAt")}</TableHead>
                    <TableHead className="min-w-64">{t("push.error")}</TableHead>
                    <TableHead aria-label={t("common.actions")} />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {jobs.map((job) => (
                    <TableRow key={job.uuid}>
                      <TableCell className="font-medium text-foreground">{job.job ?? "—"}</TableCell>
                      <TableCell className="numeric text-xs text-muted-foreground" dir="ltr">
                        {job.queue}
                      </TableCell>
                      <TableCell className="whitespace-nowrap text-xs text-muted-foreground">
                        {formatRelative(job.failed_at, locale)}
                      </TableCell>
                      <TableCell>
                        <p
                          className="numeric max-w-80 truncate font-mono text-xs text-destructive"
                          title={job.error}
                          dir="ltr"
                        >
                          {job.error}
                        </p>
                      </TableCell>
                      <TableCell>
                        <div className="flex items-center gap-2">
                          <Button variant="outline" size="sm" onClick={() => setRetrying(job)}>
                            <RotateCcw className="h-3.5 w-3.5" aria-hidden />
                            {t("push.retry")}
                          </Button>
                          <Button variant="ghost" size="sm" onClick={() => setForgetting(job)}>
                            <Trash2 className="h-3.5 w-3.5" aria-hidden />
                            {t("push.forget")}
                          </Button>
                        </div>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
            <Pagination page={query.data!.Page} totalPages={query.data!.Total} records={query.data!.Records} onPageChange={setPage} />
          </>
        )}
      </Card>

      <ConfirmDialog
        open={retrying !== null}
        onOpenChange={(next) => !next && setRetrying(null)}
        title={t("push.retryTitle")}
        confirmLabel={t("push.retry")}
        loading={retryMutation.isPending}
        onConfirm={() => {
          if (retrying) retryMutation.mutate(retrying.uuid);
        }}
      />
      <ConfirmDialog
        open={forgetting !== null}
        onOpenChange={(next) => !next && setForgetting(null)}
        title={t("push.forgetTitle")}
        description={t("push.forgetBody")}
        confirmLabel={t("push.forget")}
        destructive
        loading={forgetMutation.isPending}
        onConfirm={() => {
          if (forgetting) forgetMutation.mutate(forgetting.uuid);
        }}
      />
    </>
  );
}