import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { useRouter, useSearchParams } from 'next/navigation';
import { ListingsClient } from '../listings-client';

vi.mock('next/navigation', () => ({
  useRouter: vi.fn(),
  useSearchParams: vi.fn(),
}));
vi.mock('@/stores/auth', () => ({
  useAuthStore: (sel: (s: unknown) => unknown) => sel({ user: { store_id: 'legacy' }, selectedStoreId: 'store-1', memberships: [{ store_id: 'store-1' }], isLoading: false }),
}));

const listMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: { items: { list: (...a: unknown[]) => listMock(...a) } },
}));

function wrap(node: React.ReactNode) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return <QueryClientProvider client={qc}>{node}</QueryClientProvider>;
}

describe('ListingsClient', () => {
  const push = vi.fn();

  beforeEach(() => {
    push.mockClear();
    listMock.mockReset();
    vi.mocked(useRouter).mockReturnValue({
      push, back: vi.fn(), forward: vi.fn(), refresh: vi.fn(), replace: vi.fn(), prefetch: vi.fn(),
    } as unknown as ReturnType<typeof useRouter>);
    vi.mocked(useSearchParams).mockReturnValue(new URLSearchParams('') as unknown as ReturnType<typeof useSearchParams>);
    listMock.mockResolvedValue({
      data: [{
        id: 'item-1',
        title: 'Wool cardigan',
        price: 4500,
        status: 'active',
        image_url: null,
        view_count: 12,
        created_at: '2026-04-22T00:00:00Z',
        published_at: '2026-04-22T00:00:00Z',
      }],
      meta: { current_page: 1, last_page: 1 },
    });
  });

  it('renders a row and routes to detail on click', async () => {
    render(wrap(<ListingsClient />));
    await waitFor(() => expect(screen.getByText('Wool cardigan')).toBeInTheDocument());
    fireEvent.click(screen.getByText('Wool cardigan').closest('tr')!);
    expect(push).toHaveBeenCalledWith('/seller/listings/item-1');
  });

  it('clicking Needs attention pushes filter=needs-attention', async () => {
    render(wrap(<ListingsClient />));
    fireEvent.click(screen.getByRole('button', { name: /Needs attention/i }));
    expect(push).toHaveBeenCalledWith(expect.stringContaining('filter=needs-attention'));
  });

  it('changing sort updates the URL', async () => {
    render(wrap(<ListingsClient />));
    fireEvent.change(screen.getByDisplayValue('Newest'), { target: { value: 'price_desc' } });
    expect(push).toHaveBeenCalledWith(expect.stringContaining('sort=price_desc'));
  });

  it('passes status + q as query params to api.items.list', async () => {
    vi.mocked(useSearchParams).mockReturnValue(
      new URLSearchParams('status=draft&q=wool') as unknown as ReturnType<typeof useSearchParams>,
    );
    render(wrap(<ListingsClient />));
    await waitFor(() => expect(listMock).toHaveBeenCalled());
    const [storeId, params] = listMock.mock.calls[listMock.mock.calls.length - 1];
    expect(storeId).toBe('store-1');
    expect(params).toMatchObject({ status: 'draft', q: 'wool' });
  });
});
