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 AdminStores from '../page';

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

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

describe('AdminStores', () => {
  beforeEach(() => {
    listMock.mockReset();
  });

  it('renders rows with item counts and verified badge', async () => {
    listMock.mockResolvedValue({
      data: [
        {
          id: 's1',
          name: 'Revive Boutique',
          city: 'Portland',
          state: 'OR',
          is_verified: true,
          item_count: 243,
          total_sales: null,
          created_at: '2026-01-01T00:00:00Z',
        },
        {
          id: 's2',
          name: 'New Store',
          city: 'Denver',
          state: 'CO',
          is_verified: false,
          item_count: 0,
          total_sales: null,
          created_at: '2026-01-01T00:00:00Z',
        },
      ],
      meta: { current_page: 1, last_page: 1, total: 2, per_page: 15 },
    });
    render(wrap(<AdminStores />));
    await waitFor(() => expect(screen.getByText('Revive Boutique')).toBeInTheDocument());
    expect(screen.getByText('Portland, OR')).toBeInTheDocument();
    expect(screen.getByText('243')).toBeInTheDocument();
    expect(screen.getByText('Verified')).toBeInTheDocument();
    expect(screen.getByText('Pending')).toBeInTheDocument();
    expect(screen.getByText('2 stores')).toBeInTheDocument();
  });

  it('shows empty state when API returns no rows', async () => {
    listMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, total: 0, per_page: 15 },
    });
    render(wrap(<AdminStores />));
    await waitFor(() => expect(screen.getByText('No stores match.')).toBeInTheDocument());
  });

  it('typing in the search input passes q to the API', async () => {
    listMock.mockResolvedValue({ data: [], meta: { current_page: 1, last_page: 1, total: 0, per_page: 15 } });
    render(wrap(<AdminStores />));
    fireEvent.change(screen.getByPlaceholderText('Search by name…'), {
      target: { value: 'Revive' },
    });
    await waitFor(() => {
      const lastCall = listMock.mock.calls[listMock.mock.calls.length - 1][0];
      expect(lastCall).toMatchObject({ q: 'Revive' });
    });
  });

  it('shows error banner when API rejects', async () => {
    listMock.mockRejectedValue(new Error('forbidden'));
    render(wrap(<AdminStores />));
    await waitFor(() =>
      expect(screen.getByText(/Couldn't load stores/)).toBeInTheDocument(),
    );
  });
});
