// Shared, dependency-free pagination math used by list pages (e.g. PO History).
// Keeps page-size validation and out-of-range page clamping in one testable place.

export interface PaginationInput {
  /** Raw `perPage` value from the query string (may be undefined / invalid). */
  perPageParam?: string | number;
  /** Raw `page` value from the query string (may be undefined / invalid). */
  pageParam?: string | number;
  /** Total number of rows matching the current filter. */
  total: number;
  /** Allowed page sizes; anything else falls back to `defaultPerPage`. */
  options: number[];
  defaultPerPage: number;
}

export interface Pagination {
  perPage: number;
  page: number;
  totalPages: number;
  /** Rows to skip for the current page (Prisma `skip`). */
  skip: number;
  /** Rows to take for the current page (Prisma `take`). */
  take: number;
}

/**
 * Resolve a safe page size and (1-based) page number from untrusted query
 * params. `perPage` is clamped to the allowed `options`; `page` is clamped to
 * `[1, totalPages]` so an out-of-range or non-numeric page never paginates past
 * the last page.
 */
export function resolvePagination({
  perPageParam,
  pageParam,
  total,
  options,
  defaultPerPage,
}: PaginationInput): Pagination {
  const perPage = options.includes(Number(perPageParam)) ? Number(perPageParam) : defaultPerPage;
  const totalPages = Math.max(1, Math.ceil(total / perPage));
  const requested = Number(pageParam);
  const page = Math.min(
    Math.max(1, Number.isFinite(requested) && requested > 0 ? Math.floor(requested) : 1),
    totalPages,
  );
  return { perPage, page, totalPages, skip: (page - 1) * perPage, take: perPage };
}
