import { renderWithClient } from '../../../../utils/test/react-query';
import {
  mockedCheckSmsKeyReturnData,
  mockedMobile,
  mockedRestrictedMobile,
  mockedSmsKey,
  mockedWrongSmsKey
} from '../../../../mocks/data';
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/react';
import SmsKeyForm from '../sms-key-form';
import * as tempUserAPI from '../../../../api/temp-user';

describe('SmsKeyForm component', () => {
  const mockedHandleSubmit = jest.fn();
  const mockedHandleError = jest.fn();

  afterEach(() => {
    jest.resetAllMocks();
    jest.restoreAllMocks();
  });

  test('successful render component', async () => {
    const result = renderWithClient(
      <SmsKeyForm mobile={mockedMobile} onSubmit={mockedHandleSubmit} onError={mockedHandleError} />
    );
    expect(await result.findByTestId('smskey-form')).toBeInTheDocument();
    const mobileInput = await result.findByTestId('mobile-field');
    expect(mobileInput).toBeInTheDocument();
    expect(mobileInput).toHaveValue(mockedMobile);
    expect(
      await result.findByText('یک کد 6 رقمی برای شما ارسال شد، لطفا کد ارسال شده را وارد نمایید.')
    ).toBeInTheDocument();
    expect(await result.findByText(/کد احراز هویت/)).toBeInTheDocument();
    expect(await result.findByRole('button', { name: 'تایید' })).toBeInTheDocument();
  });

  test('form errors', async () => {
    const result = renderWithClient(
      <SmsKeyForm mobile={mockedMobile} onSubmit={mockedHandleSubmit} onError={mockedHandleError} />
    );
    const smsKeyField = await result.getByTestId('smsKey-field');
    const user = userEvent.setup();
    await user.type(smsKeyField, '12345');
    await user.tab();

    expect(await result.getByTestId('smsKey-field-error')).toHaveTextContent(
      'لطفا کد 6 رقمی پیامک شده به شماره خود را وارد نمایید.'
    );
  });

  describe('call checkSmsKeyRequest function', () => {
    test('correct arguments', async () => {
      const mockCheckSmsKeyRequest = jest.spyOn(tempUserAPI, 'checkSmsKeyRequest');
      const data = { mobile: mockedMobile, smsKey: mockedSmsKey };

      const result = renderWithClient(
        <SmsKeyForm
          mobile={data.mobile}
          onSubmit={mockedHandleSubmit}
          onError={mockedHandleError}
        />
      );

      const user = userEvent.setup();
      await user.type(result.getByTestId('smsKey-field'), data.smsKey);
      await user.click(await result.getByRole('button', { name: /تایید/i }));

      await waitFor(() => expect(mockCheckSmsKeyRequest).toHaveBeenCalledWith(data));
      await waitFor(() =>
        expect(mockedHandleSubmit).toHaveBeenCalledWith(
          mockedCheckSmsKeyReturnData,
          data,
          undefined
        )
      );
      await waitFor(() => expect(mockedHandleError).not.toHaveBeenCalled());
    });

    test('error 403', async () => {
      const mockCheckSmsKeyRequest = jest.spyOn(tempUserAPI, 'checkSmsKeyRequest');
      const data = { mobile: mockedRestrictedMobile, smsKey: mockedSmsKey };

      const result = renderWithClient(
        <SmsKeyForm
          mobile={data.mobile}
          onSubmit={mockedHandleSubmit}
          onError={mockedHandleError}
        />
      );

      const user = userEvent.setup();
      await user.type(result.getByTestId('smsKey-field'), data.smsKey);
      await user.click(await result.getByRole('button', { name: /تایید/i }));

      await waitFor(() => expect(mockCheckSmsKeyRequest).toHaveBeenCalledWith(data));
      await waitFor(() => expect(mockedHandleSubmit).not.toHaveBeenCalled());
      await waitFor(() => expect(mockedHandleError).toHaveBeenCalled());
    });

    test('other errors', async () => {
      const mockCheckSmsKeyRequest = jest.spyOn(tempUserAPI, 'checkSmsKeyRequest');
      const data = { mobile: mockedMobile, smsKey: mockedWrongSmsKey };

      const result = renderWithClient(
        <SmsKeyForm
          mobile={data.mobile}
          onSubmit={mockedHandleSubmit}
          onError={mockedHandleError}
        />
      );

      const user = userEvent.setup();
      await user.type(result.getByTestId('smsKey-field'), data.smsKey);
      await user.click(await result.getByRole('button', { name: /تایید/i }));
      await waitFor(() => expect(mockCheckSmsKeyRequest).toHaveBeenCalledWith(data));
      await waitFor(() => expect(mockedHandleSubmit).not.toHaveBeenCalled());
      await waitFor(() => expect(mockedHandleError).not.toHaveBeenCalled());
      await waitFor(() =>
        expect(result.getByRole('alert')).toHaveTextContent('کد وارد شده اشتباه است.')
      );
    });
  });
});
