import React from 'react';
import { fireEvent } from '@testing-library/react';
import { act } from 'react-dom/test-utils';

import renderWithTheme from '../../../testUtils/renderWithTheme';
import * as tabUtils from '../utils';

import SubTabs from '../SubTabs';

describe('SubTabs', () => {
  const onChange = jest.fn();
  const tabs = [
    { id: 1, title: 'Tab 1', panel: 'Tab content 1' },
    { id: 2, title: 'Tab 2', panel: 'Tab content 2' },
    { id: 3, title: 'Tab 3', panel: 'Tab content 3', disabled: true },
  ];

  it('renders correct selected tab', () => {
    const { getByText, queryByText } = renderWithTheme(
      <SubTabs
        id="sample-tabs"
        tabs={tabs}
        selectedTabId={1}
        onChange={onChange}
        renderActiveTabPanelOnly
      />
    );

    expect(getByText('Tab 1')).toBeInTheDocument();
    expect(getByText('Tab 2')).toBeInTheDocument();
    expect(getByText('Tab 3')).toBeInTheDocument();
    expect(getByText('Tab content 1')).toBeInTheDocument();
    expect(queryByText('Tab content 2')).not.toBeInTheDocument();
    expect(queryByText('Tab content 3')).not.toBeInTheDocument();

    fireEvent.click(getByText('Tab 3'));
    expect(onChange).not.toHaveBeenCalled();

    fireEvent.click(getByText('Tab 2'));
    expect(onChange).toHaveBeenCalledWith(2);
  });

  it('renders correct selected tab and hide inactive tabs', () => {
    const { getByText } = renderWithTheme(
      <SubTabs
        id="sample-tabs"
        tabs={tabs}
        selectedTabId={1}
        onChange={onChange}
      />
    );

    expect(getByText('Tab 1')).toBeInTheDocument();
    expect(getByText('Tab 2')).toBeInTheDocument();
    expect(getByText('Tab 3')).toBeInTheDocument();
    expect(getByText('Tab content 1')).toBeInTheDocument();
    expect(getByText('Tab content 2')).toBeInTheDocument();
    expect(getByText('Tab content 3')).toBeInTheDocument();
    expect(getByText('Tab content 2')).not.toBeVisible();
    expect(getByText('Tab content 3')).not.toBeVisible();
  });

  it('allows to hover tab using keyboard', () => {
    const WithHookSubTabs = () => {
      const [selectedTabId, setSelectedTabId] = React.useState<number | string>(
        1
      );
      return (
        <SubTabs
          id="sample-tabs"
          tabs={tabs}
          selectedTabId={selectedTabId}
          onChange={setSelectedTabId}
        />
      );
    };
    const { getByText } = renderWithTheme(<WithHookSubTabs />);

    const tab1 = getByText('Tab 1');
    const tab2 = getByText('Tab 2');
    const tab3 = getByText('Tab 3');

    // Focus tab 1
    fireEvent.click(tab1);
    expect(tab1.tabIndex).toBe(0);
    expect(tab2.tabIndex).toBe(-1);
    expect(tab3.tabIndex).toBe(-1);

    // Use arrow key to go right
    fireEvent.keyDown(tab1, { key: 'ArrowRight', keyCode: 39 });
    expect(tab1.tabIndex).toBe(-1);
    expect(tab2.tabIndex).toBe(0);
    expect(tab3.tabIndex).toBe(-1);

    // Use arrow key to go left
    fireEvent.keyDown(tab2, { key: 'ArrowLeft', keyCode: 37 });
    expect(tab1.tabIndex).toBe(0);
    expect(tab2.tabIndex).toBe(-1);
    expect(tab3.tabIndex).toBe(-1);
  });

  it('has active tab indicator', async () => {
    jest.useFakeTimers();
    const spiedGetTabWidth = jest.spyOn(tabUtils, 'getTabWidth');

    const { getByTestId } = renderWithTheme(
      <SubTabs
        id="sample-tabs"
        tabs={tabs}
        selectedTabId={2}
        onChange={onChange}
      />
    );

    const activeTabIndicator = getByTestId('active-tab-indicator');
    expect(activeTabIndicator).toBeInTheDocument();

    await act(async () => {
      jest.runAllTimers();
    });

    expect(spiedGetTabWidth).toHaveBeenCalledTimes(3);
  });
});
