import { PaginationQuery, PaginationMeta } from "../types";

/**
 * Parse common pagination/sort/search query params.
 *
 * SECURITY NOTE (trust boundary): `page` and `limit` are clamped here
 * (page ≥ 1, 1 ≤ limit ≤ 100), but `sort` and `search` are passed through
 * VERBATIM and are NOT validated against any schema. They originate from the
 * client. Callers that feed `sort` into a Prisma `orderBy` MUST allow-list it
 * against the set of sortable columns for that entity (e.g.
 * `const col = ALLOWED_SORTS.includes(sort) ? sort : "id"`), otherwise an
 * attacker-supplied field name reaches the query layer. `search` is only safe
 * when used through parameterized Prisma `contains` filters — never interpolate
 * it into raw SQL.
 */
export function parsePagination(
  query: Record<string, unknown>,
  opts?: { defaultLimit?: number; maxLimit?: number },
): {
  page: number;
  limit: number;
  skip: number;
  sort: string;
  order: "asc" | "desc";
  search: string;
} {
  // Defaults suit dense list views (25/page, capped at 100). Report endpoints
  // that render their full result set pass a generous defaultLimit/maxLimit so
  // they stay effectively complete while still bounded against a runaway scan.
  const defaultLimit = opts?.defaultLimit ?? 25;
  const maxLimit = opts?.maxLimit ?? 100;
  const page = Math.max(1, parseInt(String(query.page || "1"), 10) || 1);
  const limit = Math.min(
    maxLimit,
    Math.max(
      1,
      parseInt(
        String(query.limit || query.per_page || String(defaultLimit)),
        10,
      ) || defaultLimit,
    ),
  );
  const sort = String(query.sort || "id");
  const order =
    String(query.order || "").toLowerCase() === "asc" ? "asc" : "desc";
  const search = String(query.search || "");

  return { page, limit, skip: (page - 1) * limit, sort, order, search };
}

export function buildPaginationMeta(
  total: number,
  page: number,
  limit: number,
): PaginationMeta {
  return {
    page,
    limit,
    per_page: limit,
    total,
    total_pages: Math.ceil(total / limit),
  };
}
