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, usePathname, useSearchParams } from 'next/navigation';
import { InboxClient } from '../inbox-client';

vi.mock('next/navigation', () => ({
  useRouter: vi.fn(),
  usePathname: vi.fn(() => '/admin/inbox'),
  useSearchParams: vi.fn(),
}));

const listMock = vi.fn();
const markAllReadMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    notifications: {
      list: (...a: unknown[]) => listMock(...a),
      markAllRead: (...a: unknown[]) => markAllReadMock(...a),
      unreadCount: () => Promise.resolve({ data: { unread_count: 0 } }),
    },
  },
}));

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

const inboxRow = {
  id: 'n1',
  type: 'AdminPurchaseDisputedNotification',
  category: 'disputes',
  title: 'Dispute filed',
  body: 'Purchase #ABCD — Stripe dispute received',
  cta_url: '/admin/disputes/p1',
  icon: 'alert' as const,
  context_type: 'purchase' as const,
  context_id: 'p1',
  read_at: null,
  created_at: '2026-05-04T00:00:00Z',
};

describe('InboxClient (admin)', () => {
  const replace = vi.fn();
  let currentParams = new URLSearchParams('');

  beforeEach(() => {
    listMock.mockReset();
    markAllReadMock.mockReset();
    replace.mockReset();
    currentParams = new URLSearchParams('');
    vi.mocked(useRouter).mockReturnValue({
      replace: (url: string) => {
        replace(url);
        const qs = url.split('?')[1] ?? '';
        currentParams = new URLSearchParams(qs);
      },
      push: vi.fn(), back: vi.fn(), forward: vi.fn(), refresh: vi.fn(), prefetch: vi.fn(),
    } as unknown as ReturnType<typeof useRouter>);
    vi.mocked(useSearchParams).mockImplementation(
      () => currentParams as unknown as ReturnType<typeof useSearchParams>,
    );
    vi.mocked(usePathname).mockReturnValue('/admin/inbox');
  });

  it('renders rows from the admin notification feed', async () => {
    listMock.mockResolvedValue({
      data: [inboxRow],
      meta: { current_page: 1, last_page: 1, total: 1, per_page: 50 },
    });
    render(wrap(<InboxClient />));
    await waitFor(() => expect(screen.getByText('Dispute filed')).toBeInTheDocument());
  });

  it('passes the admin category bundle to the API', async () => {
    listMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, total: 0, per_page: 50 },
    });
    render(wrap(<InboxClient />));
    await waitFor(() => expect(listMock).toHaveBeenCalled());
    const args = listMock.mock.calls[0][0];
    expect(args.category).toBe('disputes,account_admin,system');
    expect(args.filter).toBe('all');
  });

  it('mark all read button calls markAllRead', async () => {
    listMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, total: 0, per_page: 50 },
    });
    markAllReadMock.mockResolvedValue(undefined);
    render(wrap(<InboxClient />));
    await waitFor(() => expect(listMock).toHaveBeenCalled());
    fireEvent.click(screen.getByRole('button', { name: /Mark all read/ }));
    await waitFor(() => expect(markAllReadMock).toHaveBeenCalled());
  });

  it('toggling Unread filter writes to URL via router.replace', async () => {
    listMock.mockResolvedValue({
      data: [],
      meta: { current_page: 1, last_page: 1, total: 0, per_page: 50 },
    });
    const { rerender } = render(wrap(<InboxClient />));
    fireEvent.click(screen.getByRole('button', { name: 'Unread' }));
    expect(replace).toHaveBeenCalledWith('/admin/inbox?filter=unread');

    // Simulate the router update by re-rendering with the new searchParams
    rerender(wrap(<InboxClient />));
    await waitFor(() => {
      const lastArgs = listMock.mock.calls[listMock.mock.calls.length - 1][0];
      expect(lastArgs.filter).toBe('unread');
    });
  });
});
