import { cleanup, render, screen, within } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';

import SpoonsPage from '../../src/app/(app)/spoons/page';

const { mockUseQuery, mockPush } = vi.hoisted(() => ({
  mockUseQuery: vi.fn(),
  mockPush: vi.fn(),
}));

vi.mock('convex/react', () => ({
  useConvexAuth: () => ({ isAuthenticated: false }),
  useMutation: vi.fn(),
  useQuery: mockUseQuery,
}));

vi.mock('next/navigation', () => ({
  useParams: vi.fn(),
  useRouter: () => ({ push: mockPush, replace: vi.fn() }),
  useSearchParams: () => new URLSearchParams(),
}));

const spoon = {
  _id: 'spoon-1',
  name: 'useSend',
  upstreamOwner: 'acme',
  upstreamRepo: 'app',
  forkOwner: 'me',
  forkRepo: 'app',
  status: 'active',
  syncStatus: undefined,
  syncCadence: 'daily',
  effectiveUpstreamAheadBy: 0,
  rawUpstreamAheadBy: 0,
  forkAheadBy: 0,
  ignoredUpstreamCount: 0,
  lastCheckedAt: undefined,
};

describe('spoon list accessibility', () => {
  afterEach(() => {
    cleanup();
    mockUseQuery.mockReset();
    mockPush.mockReset();
  });

  it('does not nest interactive elements inside a role="link" container', () => {
    mockUseQuery.mockImplementation((_query, args) => {
      // threads list passes a limit; spoons list passes {}.
      if (args && 'limit' in args) return [];
      return [spoon];
    });

    const { container } = render(<SpoonsPage />);

    // Invalid ARIA nested-interactive pattern must be gone.
    expect(container.querySelector('[role="link"]')).toBeNull();
  });

  it('keeps a primary navigation link and a secondary "Open" link to the spoon detail', () => {
    mockUseQuery.mockImplementation((_query, args) => {
      if (args && 'limit' in args) return [];
      return [spoon];
    });

    render(<SpoonsPage />);

    const href = '/spoons/spoon-1';

    // Primary link: the spoon name navigates to the detail route.
    const nameLink = screen.getByRole('link', { name: /useSend/ });
    expect(nameLink).toHaveAttribute('href', href);

    // Secondary action: the "Open" link still exists and points to the detail.
    const openLink = screen.getByRole('link', { name: /open/i });
    expect(openLink).toHaveAttribute('href', href);

    // Both real anchors point at the destination; no simulated role="link".
    const links = screen.getAllByRole('link');
    for (const link of links.filter((el) => within(el).queryByText('useSend'))) {
      expect(link).toHaveAttribute('href', href);
    }
  });
});
