import React from 'react';
import { render, cleanup, waitFor, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';

import getOperatorData from '../../../../../tests/factories/pages/operator.factory';
import { defaultInfoGrid, twoColInfoGrid } from '../../../../constants/info-grid';
import {
  generateLabel,
  getKeyValues,
  getInfoGridColumnValues,
  latestItems,
} from '../../../../helpers/info-grid';
import InfoGrid from '.';

let data;
let gridLabels;
let gridItems;

beforeEach(() => {
  data = getOperatorData();
  gridLabels = defaultInfoGrid[data.template];
  gridItems = getKeyValues(data.relation, gridLabels, data.market);
});
describe('Show Info Grid Component', () => {
  // Template One - Grid View
  test('render with props', () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns={false} />);
    expect(container).toBeTruthy();
  });
  test('show correct components rendered / correct classes added when on grid view', async () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns={false} />);
    await waitFor(() => {
      expect(container.querySelector('.containerColumn')).toBeFalsy();
      expect(container.querySelector('.collapseContainer')).toBeTruthy();
    });
  });
  test('show collapse button when added on grid view', async () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns={false} />);
    await waitFor(() => {
      expect(container.querySelector('.collapseContainer .buttonM')).toBeTruthy();
    });
  });
  test('hide collapse button when removed on grid view', async () => {
    const { container } = render(
      <InfoGrid page={data} onlyMobile={false} showTwoColumns={false} />
    );
    await waitFor(() => {
      expect(container.querySelector('.collapseContainer .buttonM')).toBeFalsy();
    });
  });
  test('Test info grid labels for operator review', () => {
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns={false} />);

    expect(container).toBeTruthy();
    expect(container.querySelectorAll('.gridItem')).toHaveLength(8);
    expect(container.querySelector('.gridItem span')).toHaveTextContent(
      Object.values(gridLabels)[0][1]
    );
    expect(container.querySelectorAll('.gridItem')[4].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[4][1]
    );
    expect(container.querySelectorAll('.gridItem')[7].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[7][1]
    );
  });
  test('Test info grid values for operator review', () => {
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns={false} />);

    expect(container).toBeTruthy();
    expect(
      container.querySelectorAll('.gridItem')[2].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(gridItems)[2],
        Object.values(gridItems)[2],
        Object.values(gridLabels)[2][2]
      )
    );
    expect(
      container.querySelectorAll('.gridItem')[4].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(gridItems)[4],
        Object.values(gridItems)[4],
        Object.values(gridLabels)[4][2]
      )
    );
    expect(
      container.querySelectorAll('.gridItem')[6].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(gridItems)[6],
        Object.values(gridItems)[6],
        Object.values(gridLabels)[6][2]
      )
    );
  });
  test('Test info grid labels for game review', () => {
    data = {
      ...data,
      template: 'game_review',
    };
    gridLabels = defaultInfoGrid.game_review;
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns={false} />);

    expect(container).toBeTruthy();
    expect(container.querySelectorAll('.gridItem')).toHaveLength(9);
    expect(container.querySelector('.gridItem span')).toHaveTextContent(
      Object.values(gridLabels)[0][1]
    );
    expect(container.querySelectorAll('.gridItem')[4].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[4][1]
    );
    expect(container.querySelectorAll('.gridItem')[8].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[8][1]
    );
  });
  test('If labels are not found for a particular template, use operator review template as a default', () => {
    data = {
      ...data,
      template: 'sportsbook_review',
    };
    gridLabels = defaultInfoGrid.sportsbook_review || Object.values(defaultInfoGrid)[0];

    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns={false} />);

    expect(container).toBeTruthy();
    expect(container.querySelectorAll('.gridItem')).toHaveLength(8);
    expect(container.querySelector('.gridItem span')).toHaveTextContent(
      Object.values(gridLabels)[0][1]
    );
    expect(container.querySelectorAll('.gridItem')[4].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[4][1]
    );
    expect(container.querySelectorAll('.gridItem')[7].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[7][1]
    );
  });
  test('Hide Show more items button on template one grid view', () => {
    const { container } = render(<InfoGrid page={data} />);

    expect(container.querySelector('.singleColumnSeeMore')).toBeFalsy();
  });

  // Template One - Column View
  test('show correct column headings when on two column view', () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns />);
    expect(container.querySelectorAll('.header span')[0].innerHTML.split('</div>')[1]).toBe(
      'General Info'
    );
    expect(container.querySelectorAll('.header span')[1].innerHTML.split('</div>')[1]).toBe(
      'Casino Details'
    );
  });
  test('show correct classes when on two column view', () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns />);
    expect(container.querySelector('.collapseContainer')).toBeFalsy();
    expect(container.querySelector('.containerColumn')).toBeTruthy();
  });
  test('hide collapse button when on two column view', async () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns />);
    await waitFor(() => {
      expect(container.querySelector('.collapseContainer .buttonM')).toBeFalsy();
    });
  });
  test('Test info grid labels for two column view for operator review', () => {
    gridLabels = twoColInfoGrid[data.template];
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns />);

    expect(container).toBeTruthy();
    expect(container.querySelector('.gridItem span')).toHaveTextContent(
      Object.values(Object.values(gridLabels)[0])[0][1]
    );
    expect(container.querySelectorAll('.gridItem')[1].querySelector('span')).toHaveTextContent(
      Object.values(Object.values(gridLabels)[0])[1][1]
    );
  });
  test('Test info grid values for two column view on operator review', () => {
    gridLabels = twoColInfoGrid[data.template];
    gridItems = getInfoGridColumnValues(data.relation, gridLabels, data.market);
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns />);

    expect(container).toBeTruthy();
    expect(
      container.querySelectorAll('.gridItem')[0].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(Object.values(Object.values(gridItems))[0])[0],
        Object.values(Object.values(Object.values(gridItems))[0])[0],
        Object.values(Object.values(Object.values(gridLabels))[0])[0][2]
      )
    );
    expect(
      container.querySelectorAll('.gridItem')[1].querySelectorAll('span')[1].innerHTML
    ).toEqual(
      generateLabel(
        Object.keys(Object.values(Object.values(gridItems))[0])[1],
        Object.values(Object.values(Object.values(gridItems))[0])[1],
        Object.values(Object.values(Object.values(gridLabels))[0])[1][2]
      )
    );
  });
  test('Dont display grid lable and values when value is null or empty', () => {
    gridLabels = twoColInfoGrid[data.template];
    gridItems = getInfoGridColumnValues(data.relation, gridLabels, data.market);
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns />);

    expect(container).toBeTruthy();
    expect(container.querySelectorAll('.gridItem')).toHaveLength(9);

    // empty license therefore show next item
    expect(container.querySelectorAll('.gridItem')[2].querySelector('span')).toHaveTextContent(
      Object.values(Object.values(gridLabels)[0])[3][1]
    );
    expect(
      container.querySelectorAll('.gridItem')[2].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(Object.values(Object.values(gridItems))[0])[3],
        Object.values(Object.values(Object.values(gridItems))[0])[3],
        Object.values(Object.values(Object.values(gridLabels))[0])[3][2]
      ).trim()
    );

    // empty game categories therefore show next item
    expect(container.querySelectorAll('.gridItem')[7].querySelector('span')).toHaveTextContent(
      Object.values(Object.values(gridLabels)[1])[4][1]
    );
    expect(
      container.querySelectorAll('.gridItem')[7].querySelectorAll('span')[1]
    ).toHaveTextContent(
      generateLabel(
        Object.keys(Object.values(Object.values(gridItems))[1])[4],
        Object.values(Object.values(Object.values(gridItems))[1])[4],
        Object.values(Object.values(Object.values(gridLabels))[1])[4][2]
      )
    );
  });
  test('Test see all button on info grid values for two column view on operator review, where there are more than the limited number of values', () => {
    gridLabels = twoColInfoGrid[data.template];
    gridItems = getInfoGridColumnValues(data.relation, gridLabels, data.market);
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns />);
    const button = container.querySelectorAll('.general')[1].querySelector('button');

    expect(container).toBeTruthy();
    expect(button).toBeTruthy();
    expect(button).toHaveTextContent('See all');
  });
  test('Test button click on info grid values for two column view on operator review, where there are more item than the limit', async () => {
    gridLabels = twoColInfoGrid[data.template];
    gridItems = getInfoGridColumnValues(data.relation, gridLabels, data.market);
    const { container } = render(<InfoGrid page={data} showEmojis showTwoColumns />);

    expect(container.querySelector('button')).toBeTruthy();
    expect(container.querySelector('button')).toHaveTextContent('See all');

    fireEvent.click(container.querySelector('button'));

    await waitFor(() => {
      expect(container.querySelector('button')).toBeFalsy();
      expect(
        container.querySelectorAll('.gridItem')[4].querySelectorAll('span')[1]
      ).toHaveTextContent(latestItems(data.relation.software));
    });
  });
  test('Hide Show more items button on template one column view', () => {
    const { container } = render(<InfoGrid page={data} showTwoColumns />);

    expect(container.querySelector('.singleColumnSeeMore')).toBeFalsy();
  });

  // Template Two - Single Column View
  test('Test info grid labels for template two', () => {
    const { container } = render(
      <InfoGrid page={data} showSeeMoreButton showEmojis onlyMobile={false} />
    );

    expect(container).toBeTruthy();
    expect(container.querySelector('.singleColumn')).toBeTruthy();
    expect(container.querySelector('.columnItem')).toBeTruthy();
    expect(container.querySelectorAll('.columnItem')).toHaveLength(6);
    expect(container.querySelector('.columnItem span')).toHaveTextContent(
      Object.values(gridLabels)[0][1]
    );
    expect(container.querySelectorAll('.columnItem')[3].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[3][1]
    );
    expect(container.querySelectorAll('.columnItem')[4].querySelector('span')).toHaveTextContent(
      Object.values(gridLabels)[4][1]
    );
  });
  test('Display Show more items button on template two', () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);

    expect(container.querySelector('.singleColumnSeeMore')).toBeTruthy();
    expect(container.querySelector('.singleColumnSeeMore')).toHaveTextContent('Show more items');
  });
  test('Test Show more items button click on template two', () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);

    const button = container.querySelector('.singleColumnSeeMore');

    // test before click
    expect(container.querySelectorAll('.columnItem')).toHaveLength(6);
    expect(button).toBeTruthy();
    expect(button).toHaveTextContent('Show more items');

    fireEvent.click(button);

    // test after click
    expect(container.querySelectorAll('.columnItem')).toHaveLength(8);
    expect(button).toHaveTextContent('Show less items');
  });
  test('Show how many remaining as button where there is too many items to display in each block', () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);
    fireEvent.click(container.querySelector('.singleColumnSeeMore'));

    expect(container.querySelectorAll('.columnItem')[3].querySelector('button')).toBeTruthy();
    expect(container.querySelectorAll('.columnItem')[3].querySelector('button')).toHaveTextContent(
      '1 more'
    );
    expect(container.querySelectorAll('.columnItem')[7].querySelector('.wrapper')).toBeTruthy();
  });
  test('Show how many remaining as button where there is too many items to display in each block, and on click, show all items', async () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);
    fireEvent.click(container.querySelector('.singleColumnSeeMore'));

    const button = container.querySelectorAll('.columnItem')[3].querySelector('button');

    await waitFor(() => {
      expect(button).toBeTruthy();
      expect(button).toHaveTextContent('1 more');

      fireEvent.click(button);

      expect(container.querySelectorAll('.columnItem')[3].querySelector('button')).toBeFalsy();
      expect(container.querySelectorAll('.columnItem')[3]).toHaveTextContent(
        latestItems(data.relation.bonus.deposit_methods)
      );
    });
  });
  test('Show remaining items as tooltip with see more text where there is too many items to display in each block', () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);
    fireEvent.click(container.querySelector('.singleColumnSeeMore'));

    expect(container.querySelectorAll('.columnItem')[3].querySelector('button')).toHaveTextContent(
      '1 more'
    );
  });
  test('Show remaining items as tooltip with see more text where there is too many items to display in each block, and on hover of see more text, show remaining items', async () => {
    const { container } = render(<InfoGrid page={data} showSeeMoreButton onlyMobile={false} />);
    fireEvent.click(container.querySelector('.singleColumnSeeMore'));

    expect(container.querySelectorAll('.columnItem')[7].querySelector('.wrapper')).toBeTruthy();
    expect(
      container.querySelectorAll('.columnItem')[7].querySelector('.wrapper')
    ).toHaveTextContent('see more');
    expect(container.querySelectorAll('.columnItem')[7].querySelector('button')).toBeFalsy();

    fireEvent.mouseEnter(container.querySelector('.wrapper'));

    await waitFor(() => {
      expect(container.querySelector('.tooltip')).toHaveTextContent(
        latestItems(data.relation.software, null, 5)
      );
    });
  });
});
afterEach(() => {
  cleanup();
});
