import { afterEach, describe, expect, test, vi } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import { mockQuery } from '../../../test-utils/query';
import type { LidarrRequest } from '$lib/api/types';

// Wrap useQueryClient so the page can call invalidateQueries() without a
// real QueryClient context. Everything else from svelte-query passes through.
vi.mock('$lib/api/admin', () => ({
  createAdminRequestsQuery: vi.fn(),
  createQualityProfilesQuery: vi.fn(),
  createRootFoldersQuery: vi.fn(),
  approveRequest: vi.fn(),
  rejectRequest: vi.fn()
}));

import AdminRequestsPage from './+page.svelte';
import {
  createAdminRequestsQuery,
  createQualityProfilesQuery,
  createRootFoldersQuery,
  approveRequest,
  rejectRequest
} from '$lib/api/admin';

const baseRow: LidarrRequest = {
  id: 'r1',
  user_id: 'u1234567-aaaa-bbbb-cccc-deadbeef0001',
  status: 'pending',
  kind: 'album',
  lidarr_artist_mbid: 'a-mbid',
  lidarr_album_mbid: 'al-mbid',
  artist_name: 'Boards of Canada',
  album_title: 'Geogaddi',
  requested_at: '2026-04-29T10:00:00Z',
  updated_at: '2026-04-29T10:00:00Z',
  imported_album_count: 0,
  imported_track_count: 0
};

afterEach(() => vi.clearAllMocks());

function setup(rows: LidarrRequest[] = [baseRow]) {
  (createAdminRequestsQuery as ReturnType<typeof vi.fn>).mockReturnValue(
    mockQuery({ data: rows })
  );
  (createQualityProfilesQuery as ReturnType<typeof vi.fn>).mockReturnValue(
    mockQuery({ data: [{ id: 1, name: 'Standard' }] })
  );
  (createRootFoldersQuery as ReturnType<typeof vi.fn>).mockReturnValue(
    mockQuery({ data: [{ path: '/music', accessible: true, free_space: 0 }] })
  );
  return render(AdminRequestsPage);
}

describe('/admin/requests', () => {
  test('Tab switch refetches with new status filter', async () => {
    setup();
    await fireEvent.click(screen.getByRole('tab', { name: /approved/i }));
    expect(createAdminRequestsQuery).toHaveBeenCalledWith('approved');
  });

  test('Approve without override fires POST with no override body', async () => {
    setup();
    (approveRequest as ReturnType<typeof vi.fn>).mockResolvedValueOnce(baseRow);
    await fireEvent.click(screen.getByRole('button', { name: /approve geogaddi/i }));
    expect(approveRequest).toHaveBeenCalledWith('r1');
  });

  test('Override modal Confirm sends chosen values', async () => {
    setup();
    await fireEvent.click(screen.getByRole('button', { name: /override geogaddi/i }));
    await fireEvent.change(screen.getByLabelText(/quality profile/i), {
      target: { value: '1' }
    });
    await fireEvent.change(screen.getByLabelText(/root folder/i), {
      target: { value: '/music' }
    });
    (approveRequest as ReturnType<typeof vi.fn>).mockResolvedValueOnce(baseRow);
    await fireEvent.click(
      screen.getByRole('button', { name: /approve with override/i })
    );
    expect(approveRequest).toHaveBeenCalledWith('r1', {
      quality_profile_id: 1,
      root_folder_path: '/music'
    });
  });

  test('Reject opens notes textarea; confirm sends notes', async () => {
    setup();
    await fireEvent.click(screen.getByRole('button', { name: /reject geogaddi/i }));
    const textarea = screen.getByLabelText(/notes/i) as HTMLTextAreaElement;
    await fireEvent.input(textarea, { target: { value: 'duplicate' } });
    (rejectRequest as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
      ...baseRow,
      status: 'rejected'
    });
    await fireEvent.click(
      screen.getByRole('button', { name: /confirm reject/i })
    );
    expect(rejectRequest).toHaveBeenCalledWith('r1', 'duplicate');
  });

  test('Lidarr-unreachable error shows toast', async () => {
    setup();
    (approveRequest as ReturnType<typeof vi.fn>).mockRejectedValueOnce({
      code: 'lidarr_unreachable',
      message: 'unreachable',
      status: 503
    });
    await fireEvent.click(screen.getByRole('button', { name: /approve geogaddi/i }));
    await waitFor(() =>
      expect(screen.getByText(/lidarr is unreachable/i)).toBeInTheDocument()
    );
  });

  test('Track-kind row renders disclosure copy about adding the album', () => {
    setup([
      {
        ...baseRow,
        kind: 'track',
        track_title: 'Roygbiv',
        album_title: 'Geogaddi'
      }
    ]);
    expect(screen.getByText(/will add the album/i)).toBeInTheDocument();
  });
});
