import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import MockAdapter from 'axios-mock-adapter';
import { apiClient, getToken, registerUnauthorizedHandler, setToken } from '@/api/client';

describe('apiClient interceptors', () => {
  let mock: MockAdapter;

  beforeEach(() => {
    mock = new MockAdapter(apiClient);
    setToken(null);
  });

  afterEach(() => {
    mock.restore();
    setToken(null);
  });

  it('attaches Bearer token from storage', async () => {
    setToken('abc123');
    mock.onGet('/auth/me').reply((config) => {
      expect(config.headers?.Authorization).toBe('Bearer abc123');
      return [200, { id: 1, username: 'alice', role: 'admin', created_at: '2026-01-01' }];
    });

    const resp = await apiClient.get('/auth/me');
    expect(resp.status).toBe(200);
  });

  it('purges token and calls the registered handler on 401', async () => {
    setToken('expired');
    const handler = vi.fn();
    registerUnauthorizedHandler(handler);

    mock.onGet('/engagements').reply(401, { error: 'token expired' });

    await expect(apiClient.get('/engagements')).rejects.toMatchObject({
      response: { status: 401 },
    });

    expect(getToken()).toBeNull();
    expect(handler).toHaveBeenCalledTimes(1);

    // Reset to avoid leaking into other tests.
    registerUnauthorizedHandler(() => {});
  });

  it('leaves the token intact on non-401 errors', async () => {
    setToken('still-valid');
    mock.onGet('/users').reply(403, { error: 'forbidden' });

    await expect(apiClient.get('/users')).rejects.toMatchObject({
      response: { status: 403 },
    });

    expect(getToken()).toBe('still-valid');
  });
});
