"use client";

import { useState } from "react";
import Link from "next/link";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { AlertTriangle, RefreshCw, Webhook } from "lucide-react";
import { toast } from "sonner";
import { PageHeader } from "@/components/shared/page-header";
import { Pagination } from "@/components/shared/pagination";
import { EmptyState, ErrorState, TableSkeleton } from "@/components/shared/states";
import { WebhookStatusBadge } from "@/components/shared/store-badges";
import { buttonVariants, Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { usePortalSession } from "@/features/portal/portal-session";
import { useI18n, useT } from "@/i18n";
import type { Locale } from "@/i18n/types";
import { friendlyErrorMessage } from "@/lib/errors";
import { formatDateTime } from "@/lib/format";
import { queryKeys } from "@/lib/query-keys";
import { WEBHOOK_EVENTS, WEBHOOK_STATUSES } from "@/services/integration";
import {
  getPortalWebhook,
  getPortalWebhooks,
  replayPortalWebhook,
  type PortalWebhookFilters,
} from "@/services/portal";
import type { WebhookDelivery, WebhookDeliveryStatus } from "@/types/store";

/**
 * What we have tried to tell this store, and what its server answered.
 *
 * The one failure in the integration with no symptom on the store's side: orders keep moving and
 * every screen looks healthy while its endpoint is down and hearing nothing. The two counts that
 * mean "you are missing updates" are promoted to banners rather than left as numbers in a row.
 */
export default function PortalWebhooksPage() {
  const t = useT();
  const { locale } = useI18n();
  const queryClient = useQueryClient();
  const { user } = usePortalSession();

  const isOwner = user?.role === "owner";
  const hasUrl = Boolean(user?.store?.webhook_url);

  const [page, setPage] = useState(1);
  const [status, setStatus] = useState<WebhookDeliveryStatus | "">("");
  const [event, setEvent] = useState("");
  const [expanded, setExpanded] = useState<string | null>(null);

  const filters: PortalWebhookFilters = { page, rows: 10, status: status || undefined, event: event || undefined };

  const { data, isLoading, isError, error, refetch } = useQuery({
    queryKey: queryKeys.portal.webhooks(filters),
    queryFn: () => getPortalWebhooks(filters),
  });

  const replay = useMutation({
    mutationFn: (uuid: string) => replayPortalWebhook(uuid),
    onSuccess: () => {
      toast.success(t("integration.replayed"));
      void queryClient.invalidateQueries({ queryKey: ["portal", "webhooks"] });
    },
    onError: (failure) => toast.error(friendlyErrorMessage(failure, t)),
  });

  const deliveries = data?.Model ?? [];
  const summary = data?.Summary;

  return (
    <div>
      <PageHeader title={t("portal.webhooks.title")} subtitle={t("portal.webhooks.subtitle")} />

      {!hasUrl ? (
        <Banner tone="warning" text={t("portal.webhooks.noUrl")}>
          {isOwner ? (
            <Link href="/portal/settings" className={buttonVariants({ size: "sm", variant: "outline" })}>
              {t("portal.webhooks.setUp")}
            </Link>
          ) : null}
        </Banner>
      ) : null}

      {summary ? (
        <div className="mb-4 grid grid-cols-2 gap-3 sm:grid-cols-4">
          <SummaryTile label={t("integration.summarySent")} value={summary.sent} />
          <SummaryTile label={t("integration.summaryPending")} value={summary.pending} warn={summary.pending > 0} />
          <SummaryTile label={t("integration.summaryFailed")} value={summary.failed} />
          <SummaryTile label={t("integration.summaryDropped")} value={summary.dropped} warn={summary.dropped > 0} />
        </div>
      ) : null}

      {summary && summary.pending > 0 ? <Banner tone="destructive" text={t("portal.webhooks.pendingWarning")} /> : null}
      {summary && summary.dropped > 0 ? <Banner tone="destructive" text={t("portal.webhooks.droppedWarning")} /> : null}

      <Card>
        <div className="flex flex-col gap-3 kap-toolbar sm:flex-row sm:items-center">
          <div className="flex items-center gap-2">
            <span className="text-xs text-muted-foreground">{t("common.status")}</span>
            <Select
              value={status || "all"}
              onValueChange={(value) => {
                setPage(1);
                setStatus(value === "all" ? "" : (value as WebhookDeliveryStatus));
              }}
            >
              <SelectTrigger className="w-[9.5rem]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">{t("common.all")}</SelectItem>
                {WEBHOOK_STATUSES.map((option) => (
                  <SelectItem key={option} value={option}>
                    {t(`integration.status.${option}`)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="flex items-center gap-2">
            <span className="text-xs text-muted-foreground">{t("integration.filterEvent")}</span>
            <Select
              value={event || "all"}
              onValueChange={(value) => {
                setPage(1);
                setEvent(value === "all" ? "" : value);
              }}
            >
              <SelectTrigger className="w-[13rem]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">{t("common.all")}</SelectItem>
                {WEBHOOK_EVENTS.map((option) => (
                  <SelectItem key={option} value={option}>
                    {option}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>

        {isLoading ? (
          <TableSkeleton rows={8} cols={6} />
        ) : isError ? (
          <ErrorState message={friendlyErrorMessage(error, t)} onRetry={() => void refetch()} />
        ) : deliveries.length === 0 ? (
          <EmptyState title={t("integration.empty")} description={t("integration.emptyHint")} icon={Webhook} />
        ) : (
          <>
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("integration.event")}</TableHead>
                    <TableHead>{t("portal.webhooks.order")}</TableHead>
                    <TableHead>{t("common.status")}</TableHead>
                    <TableHead>{t("integration.attempts")}</TableHead>
                    <TableHead>{t("integration.responseStatus")}</TableHead>
                    <TableHead>{t("common.createdAt")}</TableHead>
                    <TableHead aria-label={t("common.actions")} />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {deliveries.map((delivery) => (
                    <DeliveryRow
                      key={delivery.uuid}
                      delivery={delivery}
                      locale={locale}
                      expanded={expanded === delivery.uuid}
                      onToggle={() => setExpanded(expanded === delivery.uuid ? null : delivery.uuid)}
                      canReplay={isOwner}
                      onReplay={() => replay.mutate(delivery.uuid)}
                      replaying={replay.isPending && replay.variables === delivery.uuid}
                    />
                  ))}
                </TableBody>
              </Table>
            </div>
            <Pagination
              page={data?.Page ?? 1}
              totalPages={data?.Total ?? 1}
              records={data?.Records ?? 0}
              onPageChange={setPage}
            />
          </>
        )}
      </Card>
    </div>
  );
}

function SummaryTile({ label, value, warn }: { label: string; value: number; warn?: boolean }) {
  return (
    <Card className="p-5 sm:p-6">
      <p className="text-xs text-muted-foreground">{label}</p>
      <p className={warn ? "mt-1 text-2xl font-semibold text-destructive" : "mt-1 text-2xl font-semibold text-foreground"}>
        {value}
      </p>
    </Card>
  );
}

function Banner({
  tone,
  text,
  children,
}: {
  tone: "warning" | "destructive";
  text: string;
  children?: React.ReactNode;
}) {
  return (
    <div
      className={
        tone === "destructive"
          ? "mb-6 flex flex-wrap items-center gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive"
          : "mb-6 flex flex-wrap items-center gap-3 rounded-lg border border-warning/30 bg-warning-soft/60 p-4 text-sm text-warning"
      }
    >
      <AlertTriangle className="h-4 w-4 shrink-0" aria-hidden />
      <span className="min-w-0 flex-1">{text}</span>
      {children}
    </div>
  );
}

function DeliveryRow({
  delivery,
  locale,
  expanded,
  onToggle,
  canReplay,
  onReplay,
  replaying,
}: {
  delivery: WebhookDelivery;
  locale: Locale;
  expanded: boolean;
  onToggle: () => void;
  canReplay: boolean;
  onReplay: () => void;
  replaying: boolean;
}) {
  const t = useT();

  return (
    <>
      <TableRow>
        <TableCell>
          <button type="button" onClick={onToggle} className="text-start text-sm font-medium text-primary hover:underline">
            {delivery.event_label || delivery.event}
          </button>
          <p className="text-[0.7rem] text-muted-foreground">{delivery.event}</p>
        </TableCell>
        <TableCell className="text-sm">
          {delivery.order?.order_number ?? "—"}
          {delivery.order?.external_order_id ? (
            <p className="text-[0.7rem] text-muted-foreground">{delivery.order.external_order_id}</p>
          ) : null}
        </TableCell>
        <TableCell>
          <WebhookStatusBadge status={delivery.status} label={delivery.status_label} />
        </TableCell>
        <TableCell className="numeric text-sm">{delivery.attempts}</TableCell>
        <TableCell className="numeric text-sm">{delivery.response_status ?? "—"}</TableCell>
        <TableCell className="text-xs text-muted-foreground">{formatDateTime(delivery.created_at, locale)}</TableCell>
        <TableCell>
          {canReplay ? (
            <Button size="sm" variant="ghost" onClick={onReplay} loading={replaying} title={t("integration.replayHint")}>
              <RefreshCw aria-hidden />
              {t("integration.replay")}
            </Button>
          ) : null}
        </TableCell>
      </TableRow>

      {expanded ? (
        <TableRow>
          <TableCell colSpan={7} className="bg-muted/30">
            <DeliveryDetail delivery={delivery} locale={locale} />
          </TableCell>
        </TableRow>
      ) : null}
    </>
  );
}

/**
 * One delivery, re-read when its row opens: a delivery being retried changes its status, attempts
 * and response in the background, and opening a row is exactly when somebody wants the current
 * answer. The row already carries everything, so the panel draws at once and the fetch only
 * replaces the snapshot.
 */
function DeliveryDetail({ delivery, locale }: { delivery: WebhookDelivery; locale: Locale }) {
  const t = useT();

  const query = useQuery({
    queryKey: queryKeys.portal.webhook(delivery.uuid),
    queryFn: async () => (await getPortalWebhook(delivery.uuid)).Model,
  });

  const full = query.data ?? delivery;

  return (
    <div className="space-y-3">
      {full.error ? (
        <div>
          <p className="text-xs font-medium text-destructive">{t("integration.errorDetail")}</p>
          <p className="text-xs text-muted-foreground">{full.error}</p>
        </div>
      ) : null}

      <div className="grid gap-3 text-xs sm:grid-cols-3">
        <Detail label={t("integration.url")}>
          {query.isPending ? (
            <Skeleton className="h-4 w-40" />
          ) : (
            <span className="break-all font-mono text-[0.7rem]" dir="ltr">
              {full.url}
            </span>
          )}
        </Detail>
        <Detail label={t("integration.nextAttempt")}>
          {full.next_attempt_at ? formatDateTime(full.next_attempt_at, locale) : "—"}
        </Detail>
        <Detail label={t("integration.deliveredAt")}>
          {full.delivered_at ? formatDateTime(full.delivered_at, locale) : "—"}
        </Detail>
      </div>

      <div className="grid gap-3 lg:grid-cols-2">
        <div>
          <p className="mb-1 text-xs font-medium text-foreground">{t("integration.payload")}</p>
          <pre dir="ltr" className="max-h-72 overflow-auto rounded-md bg-background p-3 text-start text-[0.7rem] leading-relaxed">
            {JSON.stringify(full.payload, null, 2)}
          </pre>
        </div>
        <div>
          <p className="mb-1 text-xs font-medium text-foreground">{t("integration.responseBody")}</p>
          <pre dir="ltr" className="max-h-72 overflow-auto rounded-md bg-background p-3 text-start text-[0.7rem] leading-relaxed">
            {full.response_body ?? t("integration.noResponseBody")}
          </pre>
        </div>
      </div>
    </div>
  );
}

function Detail({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="min-w-0">
      <p className="text-[0.7rem] text-muted-foreground">{label}</p>
      <div className="mt-0.5 text-foreground">{children}</div>
    </div>
  );
}
