import { describe, it, expect, beforeEach, vi } from 'vitest';
import { api, setToken, clearToken, type ApiError } from '../src/api';

describe('api wrapper', () => {
  beforeEach(() => {
    clearToken();
    vi.restoreAllMocks();
  });

  it('attaches the bearer token from localStorage', async () => {
    setToken('mcpctl_pat_xyz');
    const fetchMock = vi.fn(async () => new Response(JSON.stringify({ ok: true }), {
      status: 200, headers: { 'content-type': 'application/json' },
    }));
    vi.stubGlobal('fetch', fetchMock);

    await api.get('/api/v1/agents');

    const calls = fetchMock.mock.calls as unknown as Array<[unknown, RequestInit]>;
    expect(calls.length).toBeGreaterThan(0);
    const init = calls[0]![1];
    expect(init.headers).toMatchObject({
      'Authorization': 'Bearer mcpctl_pat_xyz',
      'Content-Type': 'application/json',
    });
  });

  it('omits the bearer header when no token is set', async () => {
    const fetchMock = vi.fn(async () => new Response('[]', {
      status: 200, headers: { 'content-type': 'application/json' },
    }));
    vi.stubGlobal('fetch', fetchMock);

    await api.get('/api/v1/agents');

    const calls = fetchMock.mock.calls as unknown as Array<[unknown, RequestInit]>;
    expect(calls.length).toBeGreaterThan(0);
    const init = calls[0]![1];
    expect(init.headers).not.toHaveProperty('Authorization');
  });

  it('throws an ApiError with status + parsed body on 4xx/5xx', async () => {
    const fetchMock = vi.fn(async () => new Response(
      JSON.stringify({ error: 'nope' }),
      { status: 422, statusText: 'Unprocessable', headers: { 'content-type': 'application/json' } },
    ));
    vi.stubGlobal('fetch', fetchMock);

    await expect(api.get('/api/v1/oops')).rejects.toMatchObject({
      status: 422,
      body: { error: 'nope' },
    } satisfies Partial<ApiError>);
  });

  it('handles 204 No Content responses without parsing JSON', async () => {
    const fetchMock = vi.fn(async () => new Response(null, { status: 204 }));
    vi.stubGlobal('fetch', fetchMock);

    const result = await api.delete('/api/v1/prompts/abc');
    expect(result).toBeUndefined();
  });
});
