import { afterEach, describe, expect, test, vi } from 'vitest';
import { removeTrack } from './tracks';

afterEach(() => {
  vi.unstubAllGlobals();
});

function stubFetch(status: number, body: unknown, init: Partial<Response> = {}) {
  const res = new Response(
    body === null ? null : JSON.stringify(body),
    { status, headers: { 'Content-Type': 'application/json' }, ...init }
  );
  const spy = vi.fn().mockResolvedValue(res);
  vi.stubGlobal('fetch', spy);
  return spy;
}

describe('removeTrack', () => {
  test('DELETEs /api/admin/tracks/:id with no query string when unmonitor unset', async () => {
    const spy = stubFetch(200, {
      deleted_track_id: 't-1',
      deleted_album_id: 'al-1'
    });

    const r = await removeTrack('t-1');
    expect(r.deleted_track_id).toBe('t-1');
    expect(r.deleted_album_id).toBe('al-1');
    expect(r.deleted_artist_id).toBeUndefined();
    expect(r.lidarr_unmonitor_failed).toBeUndefined();

    const call = spy.mock.calls[0];
    expect(call[0]).toBe('/api/admin/tracks/t-1');
    expect((call[1] as RequestInit).method).toBe('DELETE');
  });

  test('appends ?unmonitor=true when option set', async () => {
    const spy = stubFetch(200, {
      deleted_track_id: 't-1',
      lidarr_unmonitor_failed: true
    });

    const r = await removeTrack('t-1', { unmonitor: true });
    expect(r.lidarr_unmonitor_failed).toBe(true);

    const call = spy.mock.calls[0];
    expect(call[0]).toBe('/api/admin/tracks/t-1?unmonitor=true');
  });

  test('omits the query string when unmonitor: false', async () => {
    const spy = stubFetch(200, { deleted_track_id: 't-1' });

    await removeTrack('t-1', { unmonitor: false });
    const call = spy.mock.calls[0];
    expect(call[0]).toBe('/api/admin/tracks/t-1');
  });

  test('surfaces not_found as ApiError', async () => {
    stubFetch(404, { error: 'not_found' });

    await expect(removeTrack('t-1')).rejects.toMatchObject({
      code: 'not_found'
    });
  });
});
