import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
  getTagProviders,
  updateTagProvider,
  testTagProvider,
  type TagProvider,
  type TagProvidersResponse
} from './admin';

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

import { api } from './client';

describe('admin tag-sources API', () => {
  beforeEach(() => vi.clearAllMocks());

  it('getTagProviders GETs the correct path', async () => {
    const sample: TagProvidersResponse = {
      providers: [
        {
          id: 'musicbrainz',
          display_name: 'MusicBrainz',
          requires_api_key: false,
          supports: ['track_tags'],
          enabled: true,
          api_key_set: false,
          display_order: 0,
          testable: true
        }
      ],
      sources_version: 1
    };
    (api.get as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce(sample);
    const got = await getTagProviders();
    expect(api.get).toHaveBeenCalledWith('/api/admin/tag-sources');
    expect(got.providers[0].id).toBe('musicbrainz');
    expect(got.sources_version).toBe(1);
  });

  it('updateTagProvider PATCHes the right path with patch body', async () => {
    const patched: TagProvider & { version_bumped: boolean } = {
      id: 'lastfm',
      display_name: 'Last.fm',
      requires_api_key: true,
      supports: ['track_tags'],
      enabled: true,
      api_key_set: true,
      display_order: 1,
      testable: true,
      version_bumped: true
    };
    (api.patch as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce(patched);
    const got = await updateTagProvider('lastfm', { enabled: true, api_key: 'mykey' });
    expect(api.patch).toHaveBeenCalledWith(
      '/api/admin/tag-sources/lastfm',
      { enabled: true, api_key: 'mykey' }
    );
    expect(got.api_key_set).toBe(true);
    expect(got.version_bumped).toBe(true);
  });

  it('testTagProvider POSTs to /test endpoint with empty body', async () => {
    (api.post as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
      ok: true,
      duration_ms: 55
    });
    const got = await testTagProvider('musicbrainz');
    expect(api.post).toHaveBeenCalledWith('/api/admin/tag-sources/musicbrainz/test', {});
    expect(got.ok).toBe(true);
    expect(got.duration_ms).toBe(55);
  });

  it('testTagProvider returns ok=false with error string on failure', async () => {
    (api.post as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
      ok: false,
      error: 'lastfm api key not set'
    });
    const got = await testTagProvider('lastfm');
    expect(got.ok).toBe(false);
    expect(got.error).toBe('lastfm api key not set');
  });
});
