import { render } from '@testing-library/react';
import { MessageProvider, useMessage } from '../message';
import { useGetItems, UseGetItemsOptions } from './useGetItems';
import { QueryClientProviderForTest, useTranslationForTest } from '@epic/tests';
import { useQueryClient } from 'react-query';
import { getQueryKeyFromTypes } from './getQueryKeyFromTypes';

interface Supplier {
  id: string;
  name: string;
}

function TestComponent(props: Omit<UseGetItemsOptions, 'entityName'>) {
  const { t } = useTranslationForTest();
  const { message } = useMessage();
  const {
    data: suppliers,
    isSuccess,
    isError,
  } = useGetItems<Supplier>({
    entityName: 'Supplier',
    t,
    ...props,
  });
  const queryClient = useQueryClient();
  return (
    <>
      {isSuccess && suppliers ? (
        <div data-testid={'suppliers'}>
          {suppliers.map((supplier) => (
            <div key={supplier.id}>{supplier.name}</div>
          ))}
        </div>
      ) : null}
      {isError ? (
        <div data-testid={'errorMessages'}>
          {message?.message ? <div>{message.message}</div> : null}
        </div>
      ) : null}
      {isSuccess ? (
        <div data-testid="queryKey">
          {JSON.stringify(queryClient.getQueryCache().getAll()[0]?.queryKey)}
        </div>
      ) : null}
    </>
  );
}

function setup(props: Omit<UseGetItemsOptions, 'entityName'> = {}) {
  return render(
    <QueryClientProviderForTest>
      <MessageProvider>
        <TestComponent {...props} />
      </MessageProvider>
    </QueryClientProviderForTest>
  );
}

describe('useGetItems', function () {
  afterEach(() => {
    localStorage.clear();
  });

  it('should make a HTTP call', async function () {
    const { findByTestId } = setup();

    const suppliers = await findByTestId('suppliers');

    expect(suppliers.innerHTML).toMatchInlineSnapshot(
      `"<div>EpicERP Ltd</div><div>Microsoft</div>"`
    );
  });

  it('should pass request configuration to the http call', async function () {
    const { findByTestId } = setup({
      requestConfig: { params: { search: 'Epic' } },
    });

    const suppliers = await findByTestId('suppliers');

    expect(suppliers.innerHTML).toMatchInlineSnapshot(`"<div>EpicERP Ltd</div>"`);
  });

  it('should set default query key', async function () {
    const { findByTestId } = setup();

    const queryKey = await findByTestId('queryKey');

    expect(JSON.parse(queryKey.innerHTML)).toMatchInlineSnapshot(`"api/supplier/"`);
  });

  it('should set query key to given key', async function () {
    const { findByTestId } = setup({
      queryKey: [...getQueryKeyFromTypes(['supplier', 'SupplierPayment'])],
    });

    const queryKey = await findByTestId('queryKey');

    expect(JSON.parse(queryKey.innerHTML)).toMatchInlineSnapshot(`
      Array [
        "api/supplier/",
        "api/supplierpayment/",
      ]
    `);
  });

  

// Below tests were first versions, using local storage to indicate an error response. 
// These tests are replaced below. We should override the endpoints in the tests for error response. See blog post comments for more details.

//   it('should send default translated error message to the MessageContext, if no error message is given', async function () {
//     localStorage.setItem('500', 'true');
//     const { findByTestId } = setup();

//     const errorMessage = await findByTestId('errorMessages');

//     expect(errorMessage.innerHTML).toMatchInlineSnapshot(
//       `"<div>Loading Supplier Failed. Something Went Wrong on The Server[Translated]</div>"`
//     );
//   });

//   it('should send translated custom error message to the MessageContext', async function () {
//     localStorage.setItem('500', 'true');
//     const { findByTestId } = setup({
//       errorMessage: 'Custom error message.',
//     });

//     const errorMessage = await findByTestId('errorMessages');

//     expect(errorMessage.innerHTML).toMatchInlineSnapshot(
//       `"<div>Custom error message. Something Went Wrong on The Server[Translated]</div>"`
//     );
//   });
// });

function mockErrorResponse() {
    server.use(
      rest.get(`${baseUrl}/${supplierKey}`, (_req, res, ctx) => {
        return res.once(
          ctx.status(500),
          ctx.json({ detail: 'Something Went Wrong on The Server' })
        );
      })
    );
  }

  it('should send default translated error message to the MessageContext, if no error message is given', async function () {
    mockErrorResponse();
    const { findByTestId } = setup();

    const suppliers = await findByTestId('errorMessages');

    expect(suppliers.innerHTML).toMatchInlineSnapshot(
      `"<div>Loading Supplier Failed. Something Went Wrong on The Server[Translated]</div>"`
    );
  });

  it('should send translated custom error message to the MessageContext', async function () {
    mockErrorResponse();
    const { findByTestId } = setup({
      errorMessage: 'Custom error message.',
    });

    const suppliers = await findByTestId('errorMessages');

    expect(suppliers.innerHTML).toMatchInlineSnapshot(
      `"<div>Custom error message. Something Went Wrong on The Server[Translated]</div>"`
    );
  });