import { renderHook } from '@testing-library/react-hooks';
import axios from 'axios';
import { localStorageKey, useClient } from './useClient';

const testApiUrl = 'http://localhost:3000/api';
jest.mock('axios');
jest.mock('@epic/environments', () => ({
  environment: {
    apiUrl: testApiUrl,
  },
}));

function setup() {
  const mockedAxios = axios as jest.Mocked<typeof axios>;
  mockedAxios.get.mockResolvedValue({ data: 'test' });
  const queries = renderHook(() => useClient());
  return { ...queries, mockedAxios };
}

const token = 'I.Am.A.Token';
localStorage.setItem(localStorageKey, token);

afterAll(() => {
  localStorage.clear();
});

describe('useClient - get', function () {
  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should prepend base api url and attach bear token and default header options', async function () {
    const { result, mockedAxios } = setup();
    await result.current.get('test');
    expect(mockedAxios.get).toHaveBeenCalledWith(`${testApiUrl}/test`, {
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
    });
  });

  it('should return body of data when called', async function () {
    const { result } = setup();

    const expected = await result.current.get('test');

    expect(expected).toEqual('test');
  });

  it('should add given custom headers', async function () {
    const { result, mockedAxios } = setup();

    await result.current.get('test', { headers: { 'X-Test': 'test' } });

    expect(mockedAxios.get).toHaveBeenCalledWith(`${testApiUrl}/test`, {
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'X-Test': 'test',
      },
    });
  });

  it('should override default header configuration with given custom headers', async function () {
    const { result, mockedAxios } = setup();

    await result.current.get('test', {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    });

    expect(mockedAxios.get).toHaveBeenCalledWith(`${testApiUrl}/test`, {
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    });
  });

  it('should add custom configs', async function () {
    const { result, mockedAxios } = setup();

    await result.current.get('test', {
      params: {
        ID: 12345,
      },
    });

    expect(mockedAxios.get).toHaveBeenCalledWith(`${testApiUrl}/test`, {
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      params: {
        ID: 12345,
      },
    });
  });

  it('getRaw should return data when called', async function () {
    const { result } = setup();

    const expected = await result.current.getRaw('test');

    expect(expected).toEqual({ data: 'test' });
  });
});