import { describe, it, expect } from "vitest";
import { resolvePagination } from "@/lib/pagination";

const OPTIONS = [25, 50, 100];
const DEFAULT = 25;

function resolve(perPageParam: string | number | undefined, pageParam: string | number | undefined, total: number) {
  return resolvePagination({ perPageParam, pageParam, total, options: OPTIONS, defaultPerPage: DEFAULT });
}

describe("resolvePagination", () => {
  it("defaults perPage and page when params are missing", () => {
    expect(resolve(undefined, undefined, 200)).toEqual({
      perPage: 25,
      page: 1,
      totalPages: 8,
      skip: 0,
      take: 25,
    });
  });

  it("accepts allowed page sizes", () => {
    expect(resolve("50", "1", 200).perPage).toBe(50);
    expect(resolve("100", "1", 200).perPage).toBe(100);
    expect(resolve(50, "1", 200).perPage).toBe(50);
  });

  it("falls back to the default for disallowed or non-numeric page sizes", () => {
    expect(resolve("10", "1", 200).perPage).toBe(25);
    expect(resolve("999", "1", 200).perPage).toBe(25);
    expect(resolve("abc", "1", 200).perPage).toBe(25);
    expect(resolve("0", "1", 200).perPage).toBe(25);
  });

  it("computes skip/take for a middle page", () => {
    const p = resolve("25", "3", 200);
    expect(p).toMatchObject({ page: 3, skip: 50, take: 25, totalPages: 8 });
  });

  it("clamps a page beyond the last page to the last page", () => {
    expect(resolve("25", "99", 200)).toMatchObject({ page: 8, totalPages: 8, skip: 175 });
  });

  it("clamps non-positive / non-numeric page to 1", () => {
    expect(resolve("25", "0", 200).page).toBe(1);
    expect(resolve("25", "-5", 200).page).toBe(1);
    expect(resolve("25", "abc", 200).page).toBe(1);
    expect(resolve("25", undefined, 200).page).toBe(1);
  });

  it("floors fractional page numbers", () => {
    expect(resolve("25", "2.9", 200).page).toBe(2);
  });

  it("always yields at least one page, even with zero rows", () => {
    expect(resolve("25", "1", 0)).toMatchObject({ page: 1, totalPages: 1, skip: 0 });
  });

  it("handles a partial final page", () => {
    // 23 rows, 25 per page -> single page holding all rows
    expect(resolve("25", "1", 23)).toMatchObject({ page: 1, totalPages: 1, take: 25 });
    // 60 rows, 25 per page -> 3 pages, last page holds 10
    expect(resolve("25", "3", 60)).toMatchObject({ page: 3, totalPages: 3, skip: 50 });
  });
});
