import pagination from '../../src/index'
import drones from '../mock/drones'
import dronesPagination1 from '../mock/dronesPagination1'
import dronesPagination2 from '../mock/dronesPagination2'

describe('Pagination', () => {
  it('should perform the pagination returning the first 5 items of the array', () => {
    expect(pagination(drones, 1, 5).items).toStrictEqual(dronesPagination1)
  })

  it('should perform the pagination returning the first 5 items, which are after the first 5 items of the array', () => {
    expect(pagination(drones, 2, 5).items).toStrictEqual(dronesPagination2)
  })

  it('should perform pagination returning 0 items if the items is null', () => {
    expect(pagination(null, 1, 5).items).toStrictEqual([])
  })

  it('should perform pagination returning 0 items if the items is undefined', () => {
    expect(pagination(undefined, 1, 5).items).toStrictEqual([])
  })

  it('should return empty items when the array is empty', () => {
    const result = pagination([], 1, 5)

    expect(result.items).toStrictEqual([])
    expect(result.AllItems).toBe(0)
    expect(result.allPages).toBe(0)
  })

  it('should clamp currentPage to 1 when it is less than 1', () => {
    const result = pagination(drones, 0, 5)

    expect(result.currentPage).toBe(1)
    expect(result.items).toStrictEqual(dronesPagination1)
  })

  it('should clamp currentPage to the last page when it exceeds total pages', () => {
    const result = pagination(drones, 99, 5)

    expect(result.currentPage).toBe(3)
    expect(result.items).toStrictEqual(drones.slice(10))
  })

  it('should use default currentPage and pageSize when they are not provided', () => {
    const items = Array.from({ length: 25 }, (_, index) => ({ id: index + 1 }))
    const result = pagination(items)

    expect(result.currentPage).toBe(1)
    expect(result.pageSize).toBe(20)
    expect(result.items).toHaveLength(20)
    expect(result.allPages).toBe(2)
    expect(result.pages).toStrictEqual([1, 2])
  })

  it('should return the last page with the remaining items', () => {
    const result = pagination(drones, 3, 5)

    expect(result.items).toHaveLength(2)
    expect(result.items).toStrictEqual(drones.slice(10))
    expect(result.startIndex).toBe(10)
    expect(result.endIndex).toBe(11)
  })

  it('should return the full pagination metadata for the first page', () => {
    const result = pagination(drones, 1, 5)

    expect(result).toStrictEqual({
      AllItems: 12,
      currentPage: 1,
      pageSize: 5,
      allPages: 3,
      startPage: 1,
      endPage: 3,
      startIndex: 0,
      endIndex: 4,
      pages: [1, 2, 3],
      items: dronesPagination1,
    })
  })

  it('should paginate a single-item array correctly', () => {
    const items = [{ id: 1, name: 'only-one' }]
    const result = pagination(items, 1, 5)

    expect(result.AllItems).toBe(1)
    expect(result.allPages).toBe(1)
    expect(result.currentPage).toBe(1)
    expect(result.items).toStrictEqual(items)
    expect(result.pages).toStrictEqual([1])
    expect(result.startIndex).toBe(0)
    expect(result.endIndex).toBe(0)
  })

  it('should limit visible page buttons when maxVisiblePages is provided', () => {
    const result = pagination(drones, 2, 5, 2)

    expect(result.currentPage).toBe(2)
    expect(result.allPages).toBe(3)
    expect(result.pages).toStrictEqual([1, 2])
    expect(result.startPage).toBe(1)
    expect(result.endPage).toBe(2)
  })

  it('should normalize invalid pageSize values to 1', () => {
    const items = [{ id: 1 }, { id: 2 }, { id: 3 }]
    const result = pagination(items, 1, 0)

    expect(result.pageSize).toBe(1)
    expect(result.allPages).toBe(3)
    expect(result.items).toHaveLength(1)
  })

  it('should keep currentPage as 1 when the collection is empty', () => {
    const result = pagination([], 1, 5)

    expect(result.currentPage).toBe(1)
    expect(result.allPages).toBe(0)
    expect(result.endIndex).toBe(-1)
  })
})
