import { renderHook } from '@testing-library/react'
import usePagination from '../hook'

const defaultProps = {
  currentPage: 0,
  setCurrentPage: vi.fn(),
  totalPages: 10,
  edgePageCount: 2,
  middlePagesSiblingCount: 1,
  truncableText: '...',
  truncableClassName: 'truncable',
}

describe('usePagination', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  describe('pages', () => {
    it('should generate correct pages array', () => {
      const { result } = renderHook(() => usePagination(defaultProps))
      expect(result.current.pages).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    })

    it('should generate empty pages for totalPages 0', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, totalPages: 0 }))
      expect(result.current.pages).toEqual([])
    })

    it('should generate single page', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, totalPages: 1 }))
      expect(result.current.pages).toEqual([1])
    })
  })

  describe('hasPreviousPage / hasNextPage', () => {
    it('should have no previous page on first page', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 1 }))
      expect(result.current.hasPreviousPage).toBe(false)
    })

    it('should have previous page when not on first page', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 3 }))
      expect(result.current.hasPreviousPage).toBe(true)
    })

    it('should have next page when not on last page', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 1 }))
      expect(result.current.hasNextPage).toBe(true)
    })

    it('should have no next page on last page', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 10 }))
      expect(result.current.hasNextPage).toBe(false)
    })
  })

  describe('middlePages', () => {
    it('should return correct middle pages when at start', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 0 }))
      // isReachedToFirst: currentPage(0) <= middlePagesSiblingCount(1), so slice(0, 3)
      expect(result.current.middlePages).toEqual([1, 2, 3])
    })

    it('should return correct middle pages when in the middle', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      // Not at start or end, slice(5-1, 5+1+1) = slice(4, 7) = [5, 6, 7]
      expect(result.current.middlePages).toEqual([5, 6, 7])
    })

    it('should return correct middle pages when at end', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 9 }))
      // isReachedToLast: currentPage(9) + middlePagesSiblingCount(1) >= totalPages(10), so slice(-3)
      expect(result.current.middlePages).toEqual([8, 9, 10])
    })
  })

  describe('previousPages and nextPages', () => {
    it('should return empty previousPages when at start', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 0 }))
      expect(result.current.previousPages).toEqual([])
    })

    it('should return previousPages when in the middle', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      // edgePageCount=2, so first 2 pages filtered by not in middlePages
      expect(result.current.previousPages).toEqual([1, 2])
    })

    it('should return empty nextPages when at end', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 9 }))
      expect(result.current.nextPages).toEqual([])
    })

    it('should return nextPages when in the middle', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      // Last 2 pages: [9, 10], filtered by not in middlePages [5,6,7]
      expect(result.current.nextPages).toEqual([9, 10])
    })
  })

  describe('truncation', () => {
    it('should be previous truncable when middle pages are far from edge', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      // previousPages=[1,2], middlePages=[5,6,7], 5 > 2+1 = true
      expect(result.current.isPreviousTruncable).toBe(true)
    })

    it('should not be previous truncable when pages are contiguous', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 2 }))
      expect(result.current.isPreviousTruncable).toBe(false)
    })

    it('should be next truncable when middle pages are far from end edge', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      // middlePages=[5,6,7], nextPages=[9,10], 7+1 < 9 = true
      expect(result.current.isNextTruncable).toBe(true)
    })

    it('should not be next truncable when pages are contiguous', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 7 }))
      expect(result.current.isNextTruncable).toBe(false)
    })
  })

  describe('passthrough values', () => {
    it('should pass through currentPage', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, currentPage: 5 }))
      expect(result.current.currentPage).toBe(5)
    })

    it('should pass through setCurrentPage', () => {
      const setCurrentPage = vi.fn()
      const { result } = renderHook(() => usePagination({ ...defaultProps, setCurrentPage }))
      result.current.setCurrentPage(3)
      expect(setCurrentPage).toHaveBeenCalledWith(3)
    })

    it('should pass through truncableText', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, truncableText: '…' }))
      expect(result.current.truncableText).toBe('…')
    })

    it('should pass through truncableClassName', () => {
      const { result } = renderHook(() => usePagination({ ...defaultProps, truncableClassName: 'custom-trunc' }))
      expect(result.current.truncableClassName).toBe('custom-trunc')
    })

    it('should use default truncableText', () => {
      const { currentPage, setCurrentPage, totalPages, edgePageCount, middlePagesSiblingCount } = defaultProps
      const { result } = renderHook(() => usePagination({ currentPage, setCurrentPage, totalPages, edgePageCount, middlePagesSiblingCount }))
      expect(result.current.truncableText).toBe('...')
    })
  })
})
