import { describe, expect, test, vi, beforeEach } from 'vitest';

vi.mock('./client', () => ({
  api: {
    get: vi.fn(),
    post: vi.fn(),
    put: vi.fn(),
    del: vi.fn()
  }
}));

import { searchLidarr } from './lidarr';
import { api } from './client';
import { qk } from './queries';
import type { LidarrSearchResult } from './types';

beforeEach(() => {
  vi.clearAllMocks();
});

describe('searchLidarr', () => {
  test('builds URL with q and kind query params', async () => {
    (api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([]);
    await searchLidarr('aphex twin', 'artist');
    expect(api.get).toHaveBeenCalledWith('/api/lidarr/search?q=aphex+twin&kind=artist');
  });

  test('encodes special characters in q (quotes, ampersands, plus)', async () => {
    (api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([]);
    await searchLidarr('boards of canada & friends', 'album');
    const calledWith = (api.get as ReturnType<typeof vi.fn>).mock.calls[0][0] as string;
    // URLSearchParams encodes space as '+' and '&' as '%26'.
    expect(calledWith).toBe(
      '/api/lidarr/search?q=boards+of+canada+%26+friends&kind=album'
    );
  });

  test('passes through results unchanged', async () => {
    const fixture: LidarrSearchResult[] = [
      {
        mbid: 'mbid-1',
        name: 'Aphex Twin',
        secondary_text: 'Electronic',
        image_url: 'https://example.test/img.jpg',
        artist_mbid: '',
        album_mbid: '',
        in_library: false,
        requested: false
      }
    ];
    (api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce(fixture);
    const out = await searchLidarr('aphex', 'artist');
    expect(out).toBe(fixture);
  });

  test('propagates errors from api.get', async () => {
    const err = { code: 'lidarr_unavailable', message: 'down', status: 503 };
    (api.get as ReturnType<typeof vi.fn>).mockRejectedValueOnce(err);
    await expect(searchLidarr('x', 'track')).rejects.toMatchObject({
      code: 'lidarr_unavailable',
      status: 503
    });
  });
});

describe('qk.lidarrSearch', () => {
  test('keys include q + kind', () => {
    expect(qk.lidarrSearch('foo', 'artist')).toEqual([
      'lidarrSearch',
      { q: 'foo', kind: 'artist' }
    ]);
  });
});
