import { renderHook, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import type { ReactNode } from 'react'
import { OrdersProvider } from './OrdersProvider.js'
import { useOrderList } from './useOrderList.js'
import type { OrdersClient } from './client.js'
import type { Order, Page } from '@platform-modules/commerce-orders'

function page(): Page<Order> {
  return { items: [], nextCursor: 'c1' }
}
function wrap(client: OrdersClient) {
  return ({ children }: { children: ReactNode }) => <OrdersProvider client={client}>{children}</OrdersProvider>
}

describe('useOrderList', () => {
  it('seeded → loading:false, no mount fetch', () => {
    const listOrders = vi.fn()
    const client: OrdersClient = { getOrderById: vi.fn(), listOrders }
    const { result } = renderHook(() => useOrderList({}, { initialData: page() }), { wrapper: wrap(client) })
    expect(result.current.loading).toBe(false)
    expect(result.current.page?.nextCursor).toBe('c1')
    expect(listOrders).not.toHaveBeenCalled()
  })

  it('unseeded → fetches on mount with the filter', async () => {
    const listOrders = vi.fn(async () => page())
    const client: OrdersClient = { getOrderById: vi.fn(), listOrders }
    const { result } = renderHook(() => useOrderList({ status: 'paid' }), { wrapper: wrap(client) })
    await waitFor(() => expect(result.current.loading).toBe(false))
    expect(listOrders).toHaveBeenCalledWith({ status: 'paid' })
  })

  it('refetches when the filter value changes (value-based key)', async () => {
    const listOrders = vi.fn(async () => page())
    const client: OrdersClient = { getOrderById: vi.fn(), listOrders }
    const { rerender } = renderHook(({ f }: { f: { status?: 'paid' | 'pending' } }) => useOrderList(f), {
      wrapper: wrap(client),
      initialProps: { f: { status: 'paid' } } as { f: { status?: 'paid' | 'pending' } },
    })
    await waitFor(() => expect(listOrders).toHaveBeenCalledTimes(1))
    rerender({ f: { status: 'pending' as const } })
    await waitFor(() => expect(listOrders).toHaveBeenCalledTimes(2))
  })

  it('client error surfaces on error', async () => {
    const client: OrdersClient = { getOrderById: vi.fn(), listOrders: async () => { throw new Error('boom') } }
    const { result } = renderHook(() => useOrderList({}), { wrapper: wrap(client) })
    await waitFor(() => expect(result.current.error?.message).toBe('boom'))
  })
})
