import { describe, it, expect, vi, beforeEach } from 'vitest';
import { apiClient } from '../api';

global.fetch = vi.fn();

const mockGetSession = vi.fn();

vi.mock('next-auth/react', () => ({
  getSession: () => mockGetSession(),
}));

describe('apiClient', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    
    mockGetSession.mockResolvedValue({
      user: {
        id: '1',
        clubs: {
          'club-1': 'owner',
        },
      },
      accessToken: 'mock-access-token',
      expires: '2099-01-01',
    });
    
    // Mock document.cookie with X-Tenant-Id
    Object.defineProperty(document, 'cookie', {
      value: 'X-Tenant-Id=club-1',
      writable: true,
      configurable: true,
    });
    
    (global.fetch as ReturnType<typeof vi.fn>).mockResolvedValue({
      ok: true,
      status: 200,
      json: async () => ({ data: 'test' }),
    });
  });

  it('should add Authorization header with access token', async () => {
    await apiClient('/api/test');

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        headers: expect.objectContaining({
          Authorization: 'Bearer mock-access-token',
        }),
      })
    );
  });

  it('should add X-Tenant-Id header with active club ID', async () => {
    await apiClient('/api/test');

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        headers: expect.objectContaining({
          'X-Tenant-Id': 'club-1',
        }),
      })
    );
  });

  it('should add Content-Type header by default', async () => {
    await apiClient('/api/test');

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        headers: expect.objectContaining({
          'Content-Type': 'application/json',
        }),
      })
    );
  });

  it('should merge custom headers with default headers', async () => {
    await apiClient('/api/test', {
      headers: {
        'Custom-Header': 'custom-value',
      },
    });

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        headers: expect.objectContaining({
          Authorization: 'Bearer mock-access-token',
          'X-Tenant-Id': 'club-1',
          'Content-Type': 'application/json',
          'Custom-Header': 'custom-value',
        }),
      })
    );
  });

  it('should allow overriding default headers', async () => {
    await apiClient('/api/test', {
      headers: {
        'Content-Type': 'text/plain',
      },
    });

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        headers: expect.objectContaining({
          'Content-Type': 'text/plain',
        }),
      })
    );
  });

  it('should pass through other fetch options', async () => {
    await apiClient('/api/test', {
      method: 'POST',
      body: JSON.stringify({ key: 'value' }),
    });

    expect(global.fetch).toHaveBeenCalledWith(
      '/api/test',
      expect.objectContaining({
        method: 'POST',
        body: JSON.stringify({ key: 'value' }),
      })
    );
  });

  it('should return Response object directly', async () => {
    const response = await apiClient('/api/test');

    expect(response.ok).toBe(true);
    expect(response.status).toBe(200);
  });

  it('should not add Authorization header when session has no token', async () => {
    mockGetSession.mockResolvedValueOnce({
      user: { id: '1', clubs: { 'club-1': 'owner' } },
      accessToken: undefined,
      expires: '2099-01-01',
    });

    await apiClient('/api/test');

    const callHeaders = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][1].headers;
    expect(callHeaders.Authorization).toBeUndefined();
  });

  it('should not add X-Tenant-Id header when no cookie present', async () => {
    Object.defineProperty(document, 'cookie', {
      value: '',
      writable: true,
      configurable: true,
    });

    await apiClient('/api/test');

    const callHeaders = (global.fetch as ReturnType<typeof vi.fn>).mock.calls[0][1].headers;
    expect(callHeaders['X-Tenant-Id']).toBeUndefined();
  });
});
