import { Breakpoint, Size } from '../common';
import { mockMatchMedia } from '../mocks';
import { render, screen } from '../test-utils';

import Decision, { DecisionPresentation, DecisionType } from '.';
import { DecisionProps } from './Decision';
import AvatarView from '../avatarView';

mockMatchMedia(jest);

describe('Decision', () => {
  const commonProps: DecisionProps = {
    options: [
      {
        media: {
          list: <AvatarView profileName="Henry Mike" />,
          block: <img src="img.jpg" alt="alt" />,
        },
        href: '#href',
        title: 'title',
        description: 'description',
        'aria-label': 'A label',
        onClick: jest.fn(),
      },
    ],
    presentation: DecisionPresentation.LIST_BLOCK,
    type: DecisionType.NAVIGATION,
  };

  const initialInnerWidth = window.innerWidth;
  const resetClientWidth = (width: number) => {
    window.innerWidth = width;
  };

  afterAll(() => {
    window.innerWidth = initialInnerWidth;
  });

  beforeEach(() => {
    resetClientWidth(Breakpoint.EXTRA_SMALL - 1);
  });

  describe(`when presentation is ${DecisionPresentation.LIST_BLOCK}`, () => {
    const props = { ...commonProps };

    it('renders only Navigation Option before first breakpoint', () => {
      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementToBeNavigationOption(element);
      expectElementNotToBeTile(element);
    });

    it('renders only Tile after first breakpoint', () => {
      resetClientWidth(Breakpoint.SMALL);

      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementNotToBeNavigationOption(element);
      expectElementToBeTile(element);
      expectElementNotToBeSmallTile(element);
    });
  });

  describe(`when presentation is ${DecisionPresentation.LIST_BLOCK_GRID}`, () => {
    const props = { ...commonProps, presentation: DecisionPresentation.LIST_BLOCK_GRID };

    it('renders only Navigation Option before first breakpoint', () => {
      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementToBeNavigationOption(element);
      expectElementNotToBeTile(element);
    });

    it('renders only Tile after first breakpoint', () => {
      resetClientWidth(Breakpoint.SMALL);

      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementNotToBeNavigationOption(element);
      expectElementToBeTile(element);
      expectElementNotToBeSmallTile(element);
    });

    it('renders container as a grid', () => {
      resetClientWidth(Breakpoint.SMALL);

      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label').parentElement;

      expect(element).toHaveClass('np-decision');
      expect(element).toHaveClass('np-decision--grid');
      expect(element).toHaveClass('flex-wrap');
    });
  });

  describe(`when presentation is ${DecisionPresentation.LIST_BLOCK} and size is Small`, () => {
    const props: DecisionProps = {
      ...commonProps,
      presentation: DecisionPresentation.LIST_BLOCK,
      size: Size.SMALL,
    };

    it('renders only Navigation Option before breakpoint', () => {
      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementToBeNavigationOption(element);
      expectElementNotToBeTile(element);
    });

    it('renders Small Tile after breakpoint', () => {
      resetClientWidth(Breakpoint.EXTRA_SMALL);

      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementNotToBeNavigationOption(element);
      expectElementToBeTile(element);
      expectElementToBeSmallTile(element);
    });
  });

  describe(`when presentation is ${DecisionPresentation.LIST}`, () => {
    const props = { ...commonProps, presentation: DecisionPresentation.LIST };

    it('renders Navigation Option before breakpoint', () => {
      render(<Decision {...props} />);
      const element = screen.getByLabelText('A label');
      expect(element).toBeInTheDocument();

      expectElementToBeNavigationOption(element);
      expectElementNotToBeTile(element);
    });
  });

  const expectElementToBeNavigationOption = (element: HTMLElement) => {
    expect(element).toHaveClass('np-navigation-option');
  };
  const expectElementNotToBeNavigationOption = (element: HTMLElement) => {
    expect(element).not.toHaveClass('np-navigation-option');
  };

  const expectElementToBeTile = (element: HTMLElement) => {
    expect(element).toHaveClass('np-tile');
  };
  const expectElementNotToBeTile = (element: HTMLElement) => {
    expect(element).not.toHaveClass('np-tile');
  };

  const expectElementToBeSmallTile = (element: HTMLElement) => {
    expect(element).toHaveClass('np-tile--small');
  };
  const expectElementNotToBeSmallTile = (element: HTMLElement) => {
    expect(element).not.toHaveClass('np-tile--small');
  };
});
