/**
 * (share/hooks — visible window sync to URL; BVA on limit/total/page).
 */
import { renderHook, act } from '@testing-library/react'
import { useVisibleCountUrlSync } from '../use-visible-count-url'

const mockReplace = jest.fn()

const mockPathname = '/en/api-products'

const mockSearchParamsRef = { current: new URLSearchParams() }

jest.mock('@/i18n/navigation', () => ({
  usePathname: () => mockPathname,
  useRouter: () => ({ replace: mockReplace }),
}))
jest.mock('next/navigation', () => ({
  useSearchParams: () => mockSearchParamsRef.current,
}))

function queryFromReplaceCall(index: number) {
  const href = String(mockReplace.mock.calls[index]?.[0] ?? '')
  return href.split('?')[1] ?? ''
}

describe('[share/hooks/use-visible-count-url]', () => {
  const defaultPageSize = 8

  beforeEach(() => {
    mockReplace.mockClear()
    mockSearchParamsRef.current = new URLSearchParams()
  })

  describe('syncVisibleWindowToUrl', () => {
    describe('limit and page query', () => {
      it('sets limit only (no page) when default parse is page 1', () => {
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(16, 100)
        })

        expect(mockReplace).toHaveBeenCalledTimes(1)
        const params = new URLSearchParams(queryFromReplaceCall(0))
        expect(params.get('page')).toBeNull()
        expect(params.get('limit')).toBe('16')
      })

      it('clears limit when visibleCount <= defaultPageSize', () => {
        mockSearchParamsRef.current = new URLSearchParams('limit=16&page=1')
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(8, 100)
        })

        const params = new URLSearchParams(queryFromReplaceCall(0))
        expect(params.get('limit')).toBeNull()
        expect(params.get('page')).toBeNull()
      })

      it('caps limit to total', () => {
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(50, 17)
        })

        expect(new URLSearchParams(queryFromReplaceCall(0)).get('limit')).toBe(
          '17'
        )
      })

      it('drops page from URL when returning to first window from page=2', () => {
        mockSearchParamsRef.current = new URLSearchParams('page=2&limit=16')
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(16, 100)
        })

        expect(mockReplace).toHaveBeenCalled()
        expect(new URLSearchParams(queryFromReplaceCall(0)).get('page')).toBeNull()
      })
    })

    describe('no-op and preservation', () => {
      it('does not replace when page and limit already match', () => {
        mockSearchParamsRef.current = new URLSearchParams('page=1&limit=16')
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(16, 100)
        })

        expect(mockReplace).not.toHaveBeenCalled()
      })

      it('preserves unrelated query keys (e.g. keyword)', () => {
        mockSearchParamsRef.current = new URLSearchParams('keyword=loan')
        const { result } = renderHook(() =>
          useVisibleCountUrlSync({ defaultPageSize })
        )

        act(() => {
          result.current.syncVisibleWindowToUrl(16, 50)
        })

        const params = new URLSearchParams(queryFromReplaceCall(0))
        expect(params.get('keyword')).toBe('loan')
        expect(params.get('limit')).toBe('16')
      })
    })
  })
})
