import { createRef } from 'react';

import { render, screen, userEvent } from '../test-utils';

import LegacyButton from './LegacyButton';
import messages from '../i18n/commonMessages/Button.messages';
import { ButtonReferenceType } from './Button.types';

describe('LegacyButton', () => {
  // eslint-disable-next-line no-console
  const originalWarn = console.warn;
  let mockedWarn: typeof originalWarn;

  const props = {
    onClick: jest.fn(),
    onFocus: jest.fn(),
    onBlur: jest.fn(),
    children: 'Send money',
  };

  beforeAll(() => {
    mockedWarn = jest.fn().mockImplementation((args) => {
      if (typeof args !== 'string' || !args.startsWith('Button has deprecated the')) {
        originalWarn(args);
      }
    });
    // eslint-disable-next-line no-console
    console.warn = mockedWarn;
  });

  beforeEach(jest.clearAllMocks);

  afterAll(() => {
    // eslint-disable-next-line no-console
    console.warn = originalWarn;
  });

  describe('by default', () => {
    it('renders the text', () => {
      render(<LegacyButton {...props} />);
      expect(screen.getByText(props.children)).toBeInTheDocument();
    });

    it('set `ref` to be true on Button', () => {
      const reference = createRef<ButtonReferenceType>();

      expect(reference.current).toBeFalsy();
      render(<LegacyButton ref={reference}>Click me!</LegacyButton>);
      expect(reference.current).toBeTruthy();
    });

    it('is not disabled', () => {
      render(<LegacyButton {...props} />);
      expect(screen.getByRole('button')).toBeEnabled();
    });
  });

  describe('button attributes', () => {
    it('sets the htmlType if set', () => {
      render(<LegacyButton {...props} htmlType="submit" />);
      expect(screen.getByRole('button')).toHaveAttribute('type', 'submit');
    });

    it('passes through custom classes if set', () => {
      render(<LegacyButton {...props} className="donkeysarethebest" />);
      expect(screen.getByRole('button')).toHaveClass('donkeysarethebest');
    });

    it('passes through aria-label if set', () => {
      render(<LegacyButton {...props} aria-label="unique label" />);
      const loadingButton = screen.getByLabelText('unique label');
      expect(loadingButton).toBeInTheDocument();
    });
  });

  describe('onClick', () => {
    it('calls onClick when clicked', async () => {
      render(<LegacyButton {...props} />);
      await userEvent.click(screen.getByRole('button'));
      expect(props.onClick).toHaveBeenCalledTimes(1);
    });

    it('does not call onClick when clicked if disabled', async () => {
      render(<LegacyButton {...props} disabled />);
      await userEvent.click(screen.getByRole('button'));
      expect(props.onClick).toHaveBeenCalledTimes(0);
    });

    it('does not call onClick when clicked if loading', async () => {
      render(<LegacyButton {...props} loading />);
      await userEvent.click(screen.getByRole('button'));
      expect(props.onClick).toHaveBeenCalledTimes(0);
    });
  });

  describe('onFocus and onBlur', () => {
    it('calls both handlers by default', async () => {
      render(<LegacyButton {...props} />);
      await userEvent.tab();
      expect(props.onFocus).toHaveBeenCalledTimes(1);
      await userEvent.tab();
      expect(props.onFocus).toHaveBeenCalledTimes(1);
    });

    it('does not call either handler if disabled', async () => {
      render(<LegacyButton {...props} disabled />);
      await userEvent.tab();
      expect(props.onFocus).not.toHaveBeenCalled();
      await userEvent.tab();
      expect(props.onFocus).not.toHaveBeenCalled();
    });

    it('calls both handlers if loading', async () => {
      render(<LegacyButton {...props} loading />);
      await userEvent.tab();
      expect(props.onFocus).toHaveBeenCalledTimes(1);
      await userEvent.tab();
      expect(props.onFocus).toHaveBeenCalledTimes(1);
    });
  });

  describe('other states', () => {
    it('renders as loading if `loading` is true', () => {
      render(<LegacyButton {...props} loading />);
      const button = screen.queryByRole('button', {
        name: messages.loadingAriaLabel.defaultMessage,
      });
      expect(button).toBeInTheDocument();
      expect(button).toBeEnabled();
      expect(button).toHaveClass('btn-loading');
      expect(button).toHaveAttribute('aria-disabled', 'true');
      expect(button).toHaveAttribute('aria-busy', 'true');
      expect(button).toHaveAttribute('aria-live', 'polite');
      expect(screen.getByTestId('ButtonProgressIndicator')).toBeInTheDocument();
    });

    it('disables the button', () => {
      render(<LegacyButton {...props} disabled />);
      const button = screen.queryByRole('button');
      expect(button).toBeDisabled();
      expect(button).toHaveClass('disabled');
      expect(button).toHaveAttribute('aria-disabled', 'false');
      expect(button).toHaveAttribute('aria-busy', 'false');
      expect(button).toHaveAttribute('aria-live', 'off');
    });
  });
});
