import Link from "next/link";
import {
  ActivityIcon,
  AlertTriangleIcon,
  ArchiveIcon,
  ArchiveRestoreIcon,
  CheckCircle2Icon,
  MinusCircleIcon,
  PauseCircleIcon,
  PlayIcon,
  Trash2Icon,
  XCircleIcon,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { PageShell } from "@/components/page-shell";
import { EmptyState } from "@/components/empty-state";
import { getSeededOperator } from "@/lib/operator";
import { listActivityRuns } from "@/lib/queries";
import {
  archiveRunAction,
  deleteRunAction,
  unarchiveRunAction,
} from "@/actions/history";
import { SwipeableRow } from "@/components/swipeable-row";
import { ResumeRunButton } from "@/components/activity/resume-run-button";

function relativeTime(date: Date | string): string {
  const d = typeof date === "string" ? new Date(date) : date;
  const diffSec = Math.floor((Date.now() - d.getTime()) / 1000);
  const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
  if (diffSec < 60) return rtf.format(-diffSec, "second");
  if (diffSec < 3600) return rtf.format(-Math.floor(diffSec / 60), "minute");
  if (diffSec < 86400) return rtf.format(-Math.floor(diffSec / 3600), "hour");
  return rtf.format(-Math.floor(diffSec / 86400), "day");
}

const RUN_STATUS_CONFIG: Record<
  string,
  { label: string; className: string; icon: React.ElementType }
> = {
  success: {
    label: "Success",
    className:
      "bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-400 border-transparent",
    icon: CheckCircle2Icon,
  },
  paused: {
    label: "Paused",
    className:
      "bg-amber-500/15 text-amber-700 dark:bg-amber-500/20 dark:text-amber-400 border-transparent",
    icon: PauseCircleIcon,
  },
  partial: {
    label: "Partial",
    className:
      "bg-amber-500/15 text-amber-700 dark:bg-amber-500/20 dark:text-amber-400 border-transparent",
    icon: AlertTriangleIcon,
  },
  failed: {
    label: "Failed",
    className:
      "bg-red-500/15 text-red-600 dark:bg-red-500/20 dark:text-red-400 border-transparent",
    icon: XCircleIcon,
  },
  skipped: {
    label: "Skipped",
    className:
      "bg-slate-200/60 text-slate-500 dark:bg-slate-700/40 dark:text-slate-400 border-transparent",
    icon: MinusCircleIcon,
  },
};

function RunStatusBadge({ status }: { status: string }) {
  const cfg = RUN_STATUS_CONFIG[status] ?? {
    label: status,
    className: "bg-secondary text-secondary-foreground border-transparent",
    icon: ActivityIcon,
  };
  const Icon = cfg.icon;
  return (
    <Badge variant="secondary" className={cfg.className}>
      <Icon className="size-3 mr-0.5" />
      {cfg.label}
    </Badge>
  );
}

type FilterValue = "success" | "paused" | "failed" | "archived";
const FILTER_TABS: { value: FilterValue; label: string }[] = [
  { value: "success", label: "Success" },
  { value: "paused", label: "Paused" },
  { value: "failed", label: "Failed" },
  { value: "archived", label: "Archived" },
];

// Partial runs (some recipients ok, some failed) surface under BOTH the
// Paused and Failed tabs — the operator wants to see anything that didn't
// fully succeed on either page. Skipped runs collapse into Archived since
// they're effectively "history that the operator chose not to send".
const FILTER_STATUSES: Record<Exclude<FilterValue, "archived">, string[]> = {
  success: ["success"],
  paused: ["paused", "partial"],
  failed: ["failed", "partial"],
};

interface PageProps {
  searchParams: Promise<{ filter?: string }>;
}

interface ShelfButtonProps {
  runId: string;
  isArchived: boolean;
}

/**
 * Left-shelf (revealed by swiping the row RIGHT). Hard-delete button.
 * iOS-Mail-style: destructive action lives on the leading edge.
 */
function DeleteShelfButton({ runId }: ShelfButtonProps) {
  return (
    <form action={deleteRunAction} className="flex w-full">
      <input type="hidden" name="runId" value={runId} />
      <button
        type="submit"
        aria-label="Delete"
        className="flex h-full w-full flex-col items-center justify-center gap-1 bg-destructive/15 text-destructive hover:bg-destructive/25 text-xs font-medium"
      >
        <Trash2Icon className="size-4" />
        Delete
      </button>
    </form>
  );
}

/**
 * Right-shelf (revealed by swiping the row LEFT). Archive (or Restore
 * when the row is already archived). Non-destructive trailing action.
 */
function ArchiveShelfButton({ runId, isArchived }: ShelfButtonProps) {
  return (
    <form
      action={isArchived ? unarchiveRunAction : archiveRunAction}
      className="flex w-full"
    >
      <input type="hidden" name="runId" value={runId} />
      <button
        type="submit"
        aria-label={isArchived ? "Restore" : "Archive"}
        className="flex h-full w-full flex-col items-center justify-center gap-1 bg-amber-500/15 text-amber-700 hover:bg-amber-500/25 dark:bg-amber-500/20 dark:text-amber-400 dark:hover:bg-amber-500/30 text-xs font-medium"
      >
        {isArchived ? (
          <ArchiveRestoreIcon className="size-4" />
        ) : (
          <ArchiveIcon className="size-4" />
        )}
        {isArchived ? "Restore" : "Archive"}
      </button>
    </form>
  );
}

export default async function ActivityPage({ searchParams }: PageProps) {
  const sp = await searchParams;
  const filter: FilterValue =
    sp.filter === "success" ||
    sp.filter === "paused" ||
    sp.filter === "failed" ||
    sp.filter === "archived"
      ? sp.filter
      : "success";
  const showingArchived = filter === "archived";

  const op = await getSeededOperator();
  const runs = await listActivityRuns(op.id, { archived: showingArchived });
  const filtered =
    filter === "archived"
      ? runs
      : runs.filter((r) => FILTER_STATUSES[filter].includes(r.status));
  const hasAny = runs.length > 0;

  return (
    <PageShell title="Activity">
      {/* Filter tabs span the full row and wrap onto a second line when the
          viewport can't fit them all. Each trigger has a small basis so they
          share space evenly while still keeping a readable label on mobile. */}
      <Tabs value={filter}>
        <TabsList className="flex w-full flex-wrap gap-1 group-data-horizontal/tabs:h-auto p-1">
          {FILTER_TABS.map(({ value, label }) => (
            <TabsTrigger
              key={value}
              value={value}
              asChild
              className="h-8 grow basis-20"
            >
              {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
              <Link href={`/activity?filter=${value}` as any}>
                {label}
              </Link>
            </TabsTrigger>
          ))}
        </TabsList>
      </Tabs>

      {filtered.length > 0 ? (
        <>
          <p className="text-xs text-muted-foreground sm:hidden">
            Swipe left to Delete, or right to {showingArchived ? "Restore" : "Archive"}.
          </p>

          {/* Mobile: swipeable cards */}
          <div className="flex flex-col gap-2 sm:hidden">
            {filtered.map((run) => {
              const clickable = run.reminderId && !run.isDeleted;
              const inner = (
                <CardContent className="flex items-center justify-between gap-3 py-3">
                  <div className="min-w-0">
                    <p className="text-sm font-medium truncate">
                      {run.reminderName}
                      {run.isDeleted && (
                        <span className="ml-1.5 text-xs font-normal text-muted-foreground italic">
                          (deleted)
                        </span>
                      )}
                    </p>
                    <p className="text-xs text-muted-foreground mt-0.5">
                      {relativeTime(run.firedAt)}
                    </p>
                  </div>
                  <RunStatusBadge status={run.status} />
                </CardContent>
              );
              const card = (
                <Card
                  size="sm"
                  className={
                    clickable
                      ? "transition-all hover:shadow-md hover:ring-primary/30 cursor-pointer rounded-none border-0 ring-0"
                      : "rounded-none border-0 ring-0"
                  }
                >
                  {clickable ? (
                    <Link
                      // eslint-disable-next-line @typescript-eslint/no-explicit-any
                      href={`/reminders/${run.reminderId}` as any}
                      className="block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                    >
                      {inner}
                    </Link>
                  ) : (
                    inner
                  )}
                </Card>
              );

              return (
                <SwipeableRow
                  // Key includes the archived flag so flipping it
                  // remounts the row with a fresh offset (closed shelf).
                  key={`${run.id}-${run.archivedAt ? "1" : "0"}`}
                  // Right swipe → reveal left shelf → Archive (non-destructive).
                  leftActions={
                    <ArchiveShelfButton runId={run.id} isArchived={Boolean(run.archivedAt)} />
                  }
                  // Left swipe → reveal right shelf → Delete (destructive).
                  rightActions={<DeleteShelfButton runId={run.id} isArchived={Boolean(run.archivedAt)} />}
                >
                  {card}
                </SwipeableRow>
              );
            })}
          </div>

          {/* Desktop: table with hover-revealed actions */}
          <div className="hidden sm:block">
            <Card>
              <CardContent className="p-0">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Reminder</TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead>Fired</TableHead>
                      <TableHead className="w-1 text-right pr-4">Actions</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {filtered.map((run) => {
                      const clickable = run.reminderId && !run.isDeleted;
                      const isArchived = Boolean(run.archivedAt);
                      return (
                        <TableRow
                          key={run.id}
                          className={clickable ? "hover:bg-muted/50" : undefined}
                        >
                          <TableCell className="font-medium">
                            {clickable ? (
                              <Link
                                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                                href={`/reminders/${run.reminderId}` as any}
                                className="block focus-visible:outline-none focus-visible:underline"
                              >
                                {run.reminderName}
                              </Link>
                            ) : (
                              <span className="text-muted-foreground italic">
                                {run.reminderName}
                                {run.isDeleted && " (deleted)"}
                              </span>
                            )}
                          </TableCell>
                          <TableCell>
                            <RunStatusBadge status={run.status} />
                          </TableCell>
                          <TableCell className="text-muted-foreground text-xs whitespace-nowrap">
                            {relativeTime(run.firedAt)}
                          </TableCell>
                          <TableCell className="text-right pr-2 whitespace-nowrap">
                            <div className="inline-flex items-center gap-0.5">
                              {run.status === "paused" && (
                                <ResumeRunButton runId={run.id} />
                              )}
                              <form
                                action={
                                  isArchived ? unarchiveRunAction : archiveRunAction
                                }
                              >
                                <input type="hidden" name="runId" value={run.id} />
                                <Button
                                  type="submit"
                                  variant="ghost"
                                  size="icon-sm"
                                  aria-label={isArchived ? "Restore" : "Archive"}
                                  className="text-muted-foreground hover:text-amber-700 dark:hover:text-amber-400"
                                >
                                  {isArchived ? (
                                    <ArchiveRestoreIcon className="size-4" />
                                  ) : (
                                    <ArchiveIcon className="size-4" />
                                  )}
                                </Button>
                              </form>
                              <form action={deleteRunAction}>
                                <input type="hidden" name="runId" value={run.id} />
                                <Button
                                  type="submit"
                                  variant="ghost"
                                  size="icon-sm"
                                  aria-label="Delete"
                                  className="text-muted-foreground hover:text-destructive"
                                >
                                  <Trash2Icon className="size-4" />
                                </Button>
                              </form>
                            </div>
                          </TableCell>
                        </TableRow>
                      );
                    })}
                  </TableBody>
                </Table>
              </CardContent>
            </Card>
          </div>
        </>
      ) : (
        <EmptyState
          icon={ActivityIcon}
          title={
            showingArchived ? "No archived runs." : `No ${filter} runs yet.`
          }
          description={
            hasAny
              ? "Runs in other states aren't shown by this filter."
              : "Reminder fire events will appear here."
          }
        />
      )}
    </PageShell>
  );
}
