"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { GripVertical } from "lucide-react";
import { ImageCard, type CardImage } from "@/components/grid/ImageCard";
import { reorderCollectionImage } from "@/app/actions/collections";
import { cn } from "@/lib/utils";

/**
 * Drag-and-drop reorderable grid. Wraps each ImageCard in a draggable
 * container; on drop, computes which image should be placed before
 * which (or at the end) and calls the server action. The grid uses the
 * same column count as the regular MasonryGrid so visuals match.
 */
export function ReorderableCollectionGrid({
  images,
  collectionId,
  view = "landscape",
}: {
  images: CardImage[];
  collectionId: number;
  view?: "portrait" | "landscape";
}) {
  // Local state mirrors the prop so we can apply optimistic reordering
  // before the server round-trips. Drift is reconciled when the page
  // re-fetches via router.refresh().
  const [items, setItems] = useState(images);
  const [draggingId, setDraggingId] = useState<number | null>(null);
  const [dropBeforeId, setDropBeforeId] = useState<number | "end" | null>(null);
  const [, start] = useTransition();
  const router = useRouter();

  if (images.length === 0) return null;

  // Reconcile when the prop changes (e.g. after a refresh).
  if (items.length !== images.length || items.some((it, i) => it.id !== images[i]?.id)) {
    setItems(images);
  }

  const cols = view === "portrait" ? "6" : "var(--grid-cols, 3)";

  function onDragStart(id: number, e: React.DragEvent) {
    setDraggingId(id);
    e.dataTransfer.effectAllowed = "move";
    // Firefox needs setData to actually begin drag.
    e.dataTransfer.setData("text/plain", String(id));
  }

  function onDragOverCard(id: number, e: React.DragEvent) {
    if (draggingId == null) return;
    e.preventDefault();
    setDropBeforeId(id);
  }

  function onDragOverEnd(e: React.DragEvent) {
    if (draggingId == null) return;
    e.preventDefault();
    setDropBeforeId("end");
  }

  function commitDrop() {
    if (draggingId == null || dropBeforeId == null) {
      setDraggingId(null);
      setDropBeforeId(null);
      return;
    }
    const movedId = draggingId;
    const beforeId = dropBeforeId === "end" ? null : dropBeforeId;
    if (movedId === beforeId) {
      setDraggingId(null);
      setDropBeforeId(null);
      return;
    }

    // Optimistic local reorder.
    setItems((cur) => {
      const fromIdx = cur.findIndex((x) => x.id === movedId);
      if (fromIdx === -1) return cur;
      const moved = cur[fromIdx];
      const without = [...cur.slice(0, fromIdx), ...cur.slice(fromIdx + 1)];
      let toIdx = beforeId == null ? without.length : without.findIndex((x) => x.id === beforeId);
      if (toIdx === -1) toIdx = without.length;
      return [...without.slice(0, toIdx), moved, ...without.slice(toIdx)];
    });

    setDraggingId(null);
    setDropBeforeId(null);

    start(async () => {
      await reorderCollectionImage(collectionId, movedId, beforeId);
      router.refresh();
    });
  }

  function onDragEnd() {
    setDraggingId(null);
    setDropBeforeId(null);
  }

  return (
    <div
      className="grid gap-5"
      style={{ gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` }}
      onDragOver={(e) => {
        // Required for the drop event to fire on this container at all
        // — without preventDefault on dragover, browsers treat the area
        // as a non-drop-target.
        if (draggingId != null) e.preventDefault();
      }}
      onDrop={commitDrop}
      onDragEnd={onDragEnd}
    >
      {items.map((img) => (
        <div
          key={img.id}
          draggable
          onDragStart={(e) => onDragStart(img.id, e)}
          onDragOver={(e) => onDragOverCard(img.id, e)}
          onDragEnd={onDragEnd}
          className={cn(
            "relative group/drag",
            draggingId === img.id && "opacity-40",
            dropBeforeId === img.id && "ring-2 ring-[var(--color-cyan)] ring-offset-2 ring-offset-[var(--color-bg-0)] rounded-2xl",
          )}
        >
          <span
            className="absolute top-3 left-3 z-20 w-7 h-7 grid place-items-center rounded-md bg-black/60 backdrop-blur-md border border-white/15 text-white/80 cursor-grab active:cursor-grabbing opacity-0 group-hover/drag:opacity-100 transition-opacity pointer-events-none"
            aria-label="Drag handle"
            title="Drag to reorder"
          >
            <GripVertical className="w-3.5 h-3.5" />
          </span>
          <ImageCard image={img} view={view} />
        </div>
      ))}
      {/* Sentinel drop zone for "end of list" */}
      <div
        onDragOver={onDragOverEnd}
        className={cn(
          "min-h-[100px] rounded-2xl border-2 border-dashed flex items-center justify-center text-xs text-[var(--color-fg-muted)] transition-colors",
          dropBeforeId === "end"
            ? "border-[var(--color-cyan)] bg-[var(--color-cyan)]/5 text-[var(--color-cyan)]"
            : "border-[var(--color-glass-border)]",
        )}
      >
        {draggingId != null ? "Drop here for end of list" : ""}
      </div>
    </div>
  );
}
