/**
 * (.cursor/skills/tcb-open-api-unit-test): branches loading / 404 / success, UX smoke, filter wiring.
 */
import React from 'react'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import ApiProductWrapper from '../index'
import { ALL_CATEGORY } from '@/constants/api-product'

jest.mock('@/i18n/navigation', () => ({
  useRouter: () => ({ replace: jest.fn() }),
}))
jest.mock('next-intl', () => ({ useTranslations: () => (k: string) => k }))
let mockFilter = { keyword: '', category: undefined as string | undefined }
const mockUpdateParam = jest.fn()
const mockOnSearchChange = jest.fn()
jest.mock('@/providers/filter-provider', () => ({
  useFilter: () => ({
    filter: mockFilter,
    updateParam: mockUpdateParam,
    onSearchChange: mockOnSearchChange,
  }),
}))
const mockUseGetApiProductCategories = jest.fn()
const mockUseGetAllApiProductsInfinite = jest.fn()
jest.mock('@/services/api-product/apiProduct.query-options', () => ({
  useGetApiProductCategories: (...args: unknown[]) =>
    mockUseGetApiProductCategories(...args),
  useGetAllApiProductsInfinite: (...args: unknown[]) =>
    mockUseGetAllApiProductsInfinite(...args),
}))
jest.mock('@/share/components/full-page/loading', () => ({
  __esModule: true,
  default: () => <div data-testid="loading-page">Loading</div>,
}))
jest.mock('@/share/layout/end-user/page', () => ({
  __esModule: true,
  default: ({ children, title }: { children: React.ReactNode; title: string }) => (
    <div>
      <h1>{title}</h1>
      {children}
    </div>
  ),
}))
jest.mock('@/share/components/input/search', () => ({
  __esModule: true,
  default: ({ onFocus }: { onFocus?: () => void }) => (
    <input placeholder="search" data-testid="search-input" onFocus={onFocus} />
  ),
}))
jest.mock('@/share/ui/button', () => ({
  Button: ({ children, onClick }: { children: React.ReactNode; onClick?: () => void }) => (
    <button type="button" onClick={onClick}>{children}</button>
  ),
}))
jest.mock('@/share/components/full-page/404', () => ({
  __esModule: true,
  default: () => <div data-testid="not-found">404</div>,
}))
jest.mock('../product-list', () => ({
  ProductList: () => <div data-testid="product-list-stub">ProductList</div>,
}))
jest.mock('@/share/ui/spinner', () => ({
  SpinnerCustom: () => <div data-testid="spinner">Spinner</div>,
}))

const defaultCategories = () => ({
  data: { data: { list: [{ name: 'Cat1' }, { name: 'Cat2' }] } },
  isFetching: false,
  isError: false,
})

const sampleProductRow = () => ({
  id: '1',
  name: 'API1',
  description: '',
  context: '',
  version: '',
  provider: '',
  status: 'PUBLISHED',
  thumbnailUrl: null,
})

const defaultProducts = () => ({
  data: {
    pages: [
      {
        data: {
          list: [sampleProductRow()],
          count: 1,
          countActive: 1,
          pagination: { limit: 10, total: 1, offset: 0, next: '', previous: '' },
        },
      },
    ],
  },
  isFetching: false,
  isFetchingNextPage: false,
  isError: false,
  isSuccess: true,
  hasNextPage: false,
  fetchNextPage: jest.fn(),
})

describe('[components/api-product/index] ApiProductWrapper', () => {
  beforeEach(() => {
    mockFilter = { keyword: '', category: undefined }
    mockUpdateParam.mockClear()
    mockOnSearchChange.mockClear()
    mockUseGetApiProductCategories.mockImplementation(defaultCategories)
    mockUseGetAllApiProductsInfinite.mockImplementation(defaultProducts)
  })

  describe('loading — categories fetching', () => {
    it('shows LoadingPage and no product shell yet', () => {
      mockUseGetApiProductCategories.mockReturnValue({
        data: null,
        isFetching: true,
        isError: false,
      })
      render(<ApiProductWrapper />)
      expect(screen.getByTestId('loading-page')).toBeInTheDocument()
      expect(screen.queryByTestId('product-list-stub')).not.toBeInTheDocument()
    })
  })

  describe('error → NotFound404', () => {
    it.each<{ label: string; patch: () => void }>([
      {
        label: 'products infinite query fails',
        patch: () =>
          mockUseGetAllApiProductsInfinite.mockReturnValue({
            data: null,
            isFetching: false,
            isError: true,
            isSuccess: false,
          }),
      },
      {
        label: 'categories query fails',
        patch: () =>
          mockUseGetApiProductCategories.mockReturnValue({
            data: null,
            isFetching: false,
            isError: true,
          }),
      },
    ])('$label', ({ patch }: { patch: () => void }) => {
      patch()
      render(<ApiProductWrapper />)
      expect(screen.getByTestId('not-found')).toBeInTheDocument()
      expect(screen.queryByTestId('product-list-stub')).not.toBeInTheDocument()
    })
  })

  describe('happy path — list shell', () => {
    it('renders layout title, filters, ProductList stub', () => {
      render(<ApiProductWrapper />)
      expect(screen.getByText('title')).toBeInTheDocument()
      expect(screen.getByTestId('product-list-stub')).toBeInTheDocument()
    })

    it('search focus keeps tree stable', async () => {
      render(<ApiProductWrapper />)
      await userEvent.click(screen.getByTestId('search-input'))
      expect(screen.getByTestId('product-list-stub')).toBeInTheDocument()
    })

    it.each<{
      category: string | undefined
      kw: string
      label: string
    }>([
      { category: undefined, kw: '', label: 'default filter' },
      { category: ALL_CATEGORY, kw: '', label: ALL_CATEGORY },
      { category: 'Retail', kw: 'loan', label: 'keyword + category' },
    ])(
      'shows ProductList for $label even when flat list empty',
      ({
        category,
        kw,
      }: {
        category: string | undefined
        kw: string
      }) => {
      mockFilter = { keyword: kw || '', category }
      mockUseGetAllApiProductsInfinite.mockReturnValue({
        data: {
          pages: [
            {
              data: {
                list: [],
                count: 0,
                countActive: 0,
                pagination: {
                  limit: 10,
                  total: 0,
                  offset: 0,
                  next: '',
                  previous: '',
                },
              },
            },
          ],
        },
        isFetching: false,
        isFetchingNextPage: false,
        isError: false,
        isSuccess: true,
        hasNextPage: false,
        fetchNextPage: jest.fn(),
      })
      render(<ApiProductWrapper />)
      expect(screen.getByTestId('product-list-stub')).toBeInTheDocument()
    })
  })

  describe('interactions — category chip', () => {
    it('category click calls updateParam with category slug', async () => {
      mockFilter = { keyword: '', category: 'Cat1' }
      render(<ApiProductWrapper />)
      await userEvent.click(screen.getByText('Cat1'))
      expect(mockUpdateParam).toHaveBeenCalledWith('category', 'Cat1')
    })
  })
})
