import { describe, expect, it } from '@jest/globals'

import { DEFAULT_PAGINATION, paginate, Pagination, paginationDecoder } from './pagination'

describe('paginate function', () => {
  const mockData = [1, 2, 3, 4, 5]

  it('should return empty data with total 0 if input data is empty', () => {
    const pagination: Pagination = { cursor: 1, limit: 10 }
    const result = paginate([], pagination)
    expect(result.data).toEqual([])
    expect(result.total).toBe(0)
    expect(result.currentPage).toBe(1)
    expect(result.perPage).toBe(10)
    expect(result.cursor).toBeNull()
  })

  it('should paginate data correctly with cursor and limit', () => {
    const pagination: Pagination = { cursor: 2, limit: 2 }
    const result = paginate(mockData, pagination)
    expect(result.data).toEqual([3, 4])
    expect(result.total).toBe(5)
    expect(result.currentPage).toBe(2)
    expect(result.perPage).toBe(2)
    expect(result.cursor).toBe(3)
  })

  it('should paginate data correctly when reaching the end', () => {
    const pagination: Pagination = { cursor: 3, limit: 2 }
    const result = paginate(mockData, pagination)
    expect(result.data).toEqual([5])
    expect(result.total).toBe(5)
    expect(result.currentPage).toBe(3)
    expect(result.perPage).toBe(2)
    expect(result.cursor).toBeNull()
  })
})

describe('paginationDecoder', () => {
  it('should validate and parse valid pagination object', () => {
    const validPagination = { cursor: 1, limit: 10 }
    const parsed = paginationDecoder.parse(validPagination)
    expect(parsed.cursor).toBe(1)
    expect(parsed.limit).toBe(10)
  })

  it('should use default limit if not provided', () => {
    const validPagination = { cursor: 1 }
    const parsed = paginationDecoder.parse(validPagination)
    expect(parsed.cursor).toBe(1)
    expect(parsed.limit).toBe(DEFAULT_PAGINATION.limit)
  })

  it('should throw error on invalid pagination object', () => {
    const invalidPagination = { cursor: 1, limit: -10 }
    expect(() => paginationDecoder.parse(invalidPagination)).toThrowError()
  })
})
