import { afterEach, describe, expect, test, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/svelte';
import { mockInfiniteQuery } from '../../../test-utils/query';
import { emptyLikesMock } from '../../../test-utils/mocks/likes';
import { pageUrlModule } from '$test-utils/mocks/appState';
import type { ArtistRef, Page } from '$lib/api/types';

const state = vi.hoisted(() => ({ pageUrl: new URL('http://localhost/search/artists?q=miles') }));

vi.mock('$app/state', () => pageUrlModule(state));

vi.mock('$lib/api/queries', () => ({
  createSearchArtistsInfiniteQuery: vi.fn()
}));

vi.mock('$lib/api/likes', () => emptyLikesMock());

import ArtistsOverflow from './+page.svelte';
import { createSearchArtistsInfiniteQuery } from '$lib/api/queries';

function page<T>(items: T[], total: number, offset = 0, limit = 50): Page<T> {
  return { items, total, offset, limit };
}

afterEach(() => {
  vi.clearAllMocks();
  state.pageUrl = new URL('http://localhost/search/artists?q=miles');
});

describe('search artists overflow', () => {
  test('renders a row per artist', () => {
    const a1: ArtistRef = { id: 'a1', name: 'Miles Davis',  sort_name: 'Miles Davis',  album_count: 12, cover_url: '' };
    const a2: ArtistRef = { id: 'a2', name: 'Miles Mosley', sort_name: 'Miles Mosley', album_count: 1,  cover_url: '' };
    (createSearchArtistsInfiniteQuery as ReturnType<typeof vi.fn>).mockReturnValue(
      mockInfiniteQuery({ pages: [page([a1, a2], 2)] })
    );
    render(ArtistsOverflow);
    expect(screen.getByRole('link', { name: /Miles Davis/ })).toBeInTheDocument();
    expect(screen.getByRole('link', { name: /Miles Mosley/ })).toBeInTheDocument();
  });

  test('Load more calls fetchNextPage when hasNextPage', async () => {
    const fetchNextPage = vi.fn();
    (createSearchArtistsInfiniteQuery as ReturnType<typeof vi.fn>).mockReturnValue(
      mockInfiniteQuery({
        pages: [page<ArtistRef>([], 100)],
        hasNextPage: true,
        fetchNextPage
      })
    );
    render(ArtistsOverflow);
    await fireEvent.click(screen.getByRole('button', { name: /load more/i }));
    expect(fetchNextPage).toHaveBeenCalledTimes(1);
  });

  test('Load more is hidden when hasNextPage is false', () => {
    (createSearchArtistsInfiniteQuery as ReturnType<typeof vi.fn>).mockReturnValue(
      mockInfiniteQuery({ pages: [page<ArtistRef>([{ id: 'a', name: 'A', sort_name: 'A', album_count: 1, cover_url: '' }], 1)] })
    );
    render(ArtistsOverflow);
    expect(screen.queryByRole('button', { name: /load more/i })).not.toBeInTheDocument();
  });

  test('empty q shows a prompt and fires no query', () => {
    state.pageUrl = new URL('http://localhost/search/artists');
    render(ArtistsOverflow);
    expect(screen.getByText(/no query/i)).toBeInTheDocument();
    expect(createSearchArtistsInfiniteQuery).not.toHaveBeenCalled();
  });
});
