import { describe, test, expect } from 'vitest';

/**
 * Tests for the pagination parameter clamping logic used across routes.
 *
 * The pattern `Math.max(0, parseInt(value) || default)` ensures that:
 * - Negative values are clamped to 0 (offset) or 1 (limit)
 * - NaN values (non-numeric strings) fall back to the default
 * - Valid positive values pass through unchanged
 *
 * This prevents PostgreSQL from rejecting negative LIMIT/OFFSET values
 * with a 500 error.
 */

// Helper that mirrors the offset clamping pattern used in routes
const clampOffset = (raw: string): number => Math.max(0, parseInt(raw) || 0);

// Helper that mirrors the limit clamping pattern used in routes (with optional upper bound)
const clampLimit = (raw: string, defaultLimit: number, maxLimit?: number): number => {
  const parsed = Math.max(1, parseInt(raw) || defaultLimit);
  return maxLimit !== undefined ? Math.min(parsed, maxLimit) : parsed;
};

describe('Pagination parameter clamping', () => {
  describe('offset clamping', () => {
    test('negative offset is clamped to 0', () => {
      expect(clampOffset('-1')).toBe(0);
      expect(clampOffset('-100')).toBe(0);
      expect(clampOffset('-999999')).toBe(0);
    });

    test('zero offset passes through', () => {
      expect(clampOffset('0')).toBe(0);
    });

    test('positive offset passes through', () => {
      expect(clampOffset('10')).toBe(10);
      expect(clampOffset('50')).toBe(50);
    });

    test('non-numeric string falls back to 0', () => {
      expect(clampOffset('abc')).toBe(0);
      expect(clampOffset('')).toBe(0);
    });
  });

  describe('limit clamping', () => {
    test('negative limit is clamped to 1', () => {
      expect(clampLimit('-1', 50)).toBe(1);
      expect(clampLimit('-5', 50)).toBe(1);
      expect(clampLimit('-100', 50)).toBe(1);
    });

    test('zero limit falls back to default (0 is falsy in JS)', () => {
      expect(clampLimit('0', 50)).toBe(50);
    });

    test('positive limit passes through', () => {
      expect(clampLimit('10', 50)).toBe(10);
      expect(clampLimit('100', 50)).toBe(100);
    });

    test('non-numeric string falls back to default', () => {
      expect(clampLimit('abc', 50)).toBe(50);
      expect(clampLimit('', 50)).toBe(50);
      expect(clampLimit('abc', 100)).toBe(100);
    });

    test('limit is capped at maxLimit when provided', () => {
      expect(clampLimit('200', 50, 100)).toBe(100); // schedules pattern (max 100)
      expect(clampLimit('2000', 100, 1000)).toBe(1000); // storage pattern (max 1000)
      expect(clampLimit('50', 50, 100)).toBe(50); // within bounds
    });
  });
});
