"use client";
import { useState, useTransition } from "react";
import { useRouter, useSearchParams, usePathname } from "next/navigation";
import { ChevronLeft, ChevronRight, ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils";

interface Props {
  currentPage: number;
  totalPages: number;
  totalCount: number;
  /** When provided, Prev/Next first try to scroll within the already-
   *  loaded grid (or prefetch + scroll, depending on mode). If the
   *  callback returns false (or resolves to false), the bar falls back
   *  to a URL navigation. */
  onScrollToPage?: (targetPage: number) => boolean | Promise<boolean>;
  /** Called when the user clicks Prev/Next but the target equals the
   *  current URL page (i.e. no router.push will happen). The grid uses
   *  this to clear its appended buffer + scroll to top, so a Prev click
   *  at "Page 5 (scrolled from URL=/)" snaps back to Page 1 instead of
   *  silently doing nothing. */
  onSamePageNav?: () => void;
}

/**
 * Bottom pagination bar. Preserves all existing query params (filters,
 * sort, view) when navigating between pages — only the `page` key
 * changes. `page=1` is dropped from the URL for a clean default.
 */
export function PaginationBar({ currentPage, totalPages, totalCount, onScrollToPage, onSamePageNav }: Props) {
  const router = useRouter();
  const pathname = usePathname();
  const sp = useSearchParams();
  const [, start] = useTransition();
  const [jump, setJump] = useState<string>("");

  // The page anchored in the URL — independent of the visible-page label
  // (which drifts as the user scrolls into appended pages). Prev/Next nav
  // math reads from here so a click at "Page 4 (showing)" while URL=?page=2
  // walks back from 2, not from 4. Without this split, a buffer of
  // appended pages combined with onEndReached chaining makes Prev appear
  // to "stick" at page 1: each Prev pushes URL=/, the auto-fetch chain
  // re-drifts visiblePage forward, and the loop never escapes.
  const urlPageRaw = Number(sp.get("page") ?? "1");
  const urlPage = Number.isFinite(urlPageRaw) && urlPageRaw >= 1
    ? Math.min(Math.floor(urlPageRaw), totalPages)
    : 1;

  const urlNav = (page: number) => {
    const next = new URLSearchParams(sp.toString());
    if (page > 1) next.set("page", String(page));
    else next.delete("page");
    const qs = next.toString();
    // If the URL would not actually change (target page === urlPage),
    // a router.push is a no-op visually and the loop "click Prev → no
    // remount → drift returns" reappears. Hand off to onSamePageNav so
    // the grid can reset its appended buffer + scroll to top.
    if (page === urlPage && onSamePageNav) {
      onSamePageNav();
      return;
    }
    // Marker so the destination grid can distinguish an internal
    // Prev/Next click from a browser back/forward. Internal nav skips
    // scroll-restore (which otherwise replays a stale buffer snapshot
    // and re-creates the visiblePage drift).
    try { sessionStorage.setItem("pinkudex:nav-internal", "1"); } catch { /* ignore */ }
    start(() => {
      router.push(qs ? `${pathname}?${qs}` : pathname, { scroll: true });
    });
  };

  const navTo = async (page: number) => {
    if (onScrollToPage) {
      const maybe = onScrollToPage(page);
      const ok = typeof maybe === "boolean" ? maybe : await maybe;
      if (ok) return;
    }
    urlNav(page);
  };

  const goJump = (e: React.FormEvent) => {
    e.preventDefault();
    const target = Number(jump);
    if (!Number.isFinite(target) || target < 1) return;
    const clamped = Math.min(Math.max(1, Math.floor(target)), totalPages);
    setJump("");
    void navTo(clamped);
  };

  // Prev/Next button math — relative to the displayed (visible) page so
  // clicks feel responsive to where the user is scrolled. The same-URL
  // case is handled by onSamePageNav (buffer reset), which prevents the
  // old "Prev does nothing" trap when target === urlPage.
  const prevTarget = Math.max(1, currentPage - 1);
  const nextTarget = Math.min(totalPages, currentPage + 1);
  const canPrev = currentPage > 1;
  const canNext = currentPage < totalPages;

  const showJump = totalPages > 5;
  return (
    <div className="flex items-center justify-center gap-2 flex-wrap">
      <button
        type="button"
        disabled={!canPrev}
        onClick={() => void navTo(prevTarget)}
        className={cn(
          "inline-flex items-center gap-1 text-sm px-3 py-1.5 rounded-lg glass",
          !canPrev
            ? "opacity-40 cursor-not-allowed"
            : "glass-hover cursor-pointer",
        )}
      >
        <ChevronLeft className="w-4 h-4" />
        Prev
      </button>

      <div className="text-sm font-mono text-[var(--color-fg-dim)] px-2 text-center tabular-nums min-w-[240px]">
        Page <span className="text-[var(--color-cyan)]">{currentPage}</span> of {totalPages}
        <span className="opacity-50"> · </span>
        {totalCount.toLocaleString()} total
      </div>

      <button
        type="button"
        disabled={!canNext}
        onClick={() => void navTo(nextTarget)}
        className={cn(
          "inline-flex items-center gap-1 text-sm px-3 py-1.5 rounded-lg glass",
          !canNext
            ? "opacity-40 cursor-not-allowed"
            : "glass-hover cursor-pointer",
        )}
      >
        Next
        <ChevronRight className="w-4 h-4" />
      </button>

      {showJump && (
        <form onSubmit={goJump} className="ml-3 inline-flex items-center gap-1.5">
          <span className="text-xs uppercase tracking-wider font-mono text-[var(--color-fg-muted)]">
            Jump to
          </span>
          <input
            type="text"
            inputMode="numeric"
            value={jump}
            onChange={(e) => setJump(e.target.value.replace(/[^0-9]/g, ""))}
            placeholder={`1–${totalPages}`}
            className="w-20 glass rounded-md px-2 py-1 text-xs font-mono outline-none focus:border-[var(--color-cyan)] text-center"
          />
          <button
            type="submit"
            disabled={!jump || Number(jump) < 1 || Number(jump) > totalPages}
            className="inline-flex items-center justify-center w-7 h-7 rounded-md glass glass-hover disabled:opacity-40 cursor-pointer"
            title="Jump"
          >
            <ArrowRight className="w-3.5 h-3.5" />
          </button>
        </form>
      )}
    </div>
  );
}
