import React from 'react';
import { cleanup, fireEvent } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';

import { ThemeProvider } from '../@styles/theme-provider';
import { render } from '../../utils/theme-render-wrapper';

import { ASSETS_URL } from '../../consts/common';
import { CustomIcon } from '../custom-icon';
import type { MainNavItem } from '../@navigation/breadcrumbs';
import { trimSpaces } from '../../utils';

import sidebarItemsMap, { sidebarItemsWithDecoratorsMap } from './__mocks__/mockSidebar';
import { Sidebar } from './sidebar';

afterEach(cleanup);

const setOpen = jest.fn();

const Provider: React.FC = ({ children }) => (
  <BrowserRouter>
    <ThemeProvider>{children}</ThemeProvider>
  </BrowserRouter>
);

describe('<Sidebar />', () => {
  it(`should render sub item after main item click`, () => {
    const { queryByText } = render(
      <Provider>
        <Sidebar
          logo=""
          open="open"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );
    const elm = queryByText(sidebarItemsMap.marketing.name);
    elm?.click();
    const subElm = queryByText(sidebarItemsMap.marketing.items?.[1]?.name || '');
    expect(subElm).toBeTruthy();
  });

  it('should render inner item after items clicks with keyboard', () => {
    const { queryByText, queryByTestId } = render(
      <Provider>
        <Sidebar
          logo=""
          open="open"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );
    const elm = queryByTestId(`menu-${trimSpaces(sidebarItemsMap.cs.name)}`);
    if (elm) {
      fireEvent.keyDown(elm, { code: 'Enter' });
    }

    const subElm = queryByTestId(
      `subMenu-${trimSpaces(sidebarItemsMap.cs.items?.[3]?.name || '')}`
    );
    if (subElm) {
      fireEvent.keyDown(subElm, { code: 'Enter' });
    }
    const innerElm = queryByText(sidebarItemsMap.cs.items?.[3]?.subItems?.[0].name || '');
    expect(innerElm).toBeTruthy();
  });

  it(`should render with closed logo and divider`, () => {
    const closedLogo = 'closedLogo';
    const { queryByText, queryByTestId } = render(
      <Provider>
        <Sidebar
          logo={<div>closedLogo</div>}
          open="closed"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );
    const elm = queryByText(closedLogo);
    expect(elm?.innerHTML).toBe(closedLogo);

    const buttonEl = queryByTestId('button-drawerLeft');
    expect(buttonEl).toBeTruthy();
  });

  it(`should render and handle mouse enter and leave events`, () => {
    const drawerWidthClose = 100;
    const drawerWidthOpen = 200;
    const { getByTestId } = render(
      <Provider>
        <Sidebar
          logo="logo"
          open="closed"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose={`${drawerWidthClose}px`}
          drawerWidthOpen={`${drawerWidthOpen}px`}
        />
      </Provider>
    );
    const elm = getByTestId('drawer');
    fireEvent.mouseEnter(elm);
    expect(setOpen).toHaveBeenCalled();
    fireEvent.mouseLeave(elm);
    expect(setOpen).toHaveBeenCalledTimes(2);
  });

  it(`should render without divider and drawer button`, () => {
    const { queryByTestId } = render(
      <Provider>
        <Sidebar
          logo=""
          open="closed"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
          showDrawerButton={false}
        />
      </Provider>
    );

    const buttonEl = queryByTestId('button-drawerLeft');
    expect(buttonEl).toBeFalsy();
  });

  it('should render item with badge', () => {
    const { queryByTestId } = render(
      <Provider>
        <Sidebar
          logo=""
          open="open"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );
    const badge = queryByTestId(`badge-${trimSpaces(sidebarItemsMap.dashboard.name)}`);
    expect(badge?.innerHTML).toBe(trimSpaces(sidebarItemsMap.dashboard.badgeText));
  });

  it('should render decorator items', () => {
    const { queryByTestId } = render(
      <Provider>
        <Sidebar
          logo=""
          open="open"
          setOpen={setOpen}
          sidebarItemsMap={sidebarItemsWithDecoratorsMap}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );
    const separator = queryByTestId(
      `separator-${trimSpaces(sidebarItemsWithDecoratorsMap.chartsSeparator.name)}`
    );
    const title = queryByTestId(`title-${trimSpaces(sidebarItemsWithDecoratorsMap.arrTitle.name)}`);

    expect(separator).toBeTruthy();
    expect(title).toBeTruthy();
  });

  it('should render badges 3 levels down', () => {
    const badgeItem1 = 'badgeItem1';
    const badgeItem2 = 'badgeItem2';
    const badgeItem3 = 'badgeItem3';

    const items: Record<string, MainNavItem> = {
      badge: {
        name: badgeItem1,
        badgeText: badgeItem1,
        Icon: () => <CustomIcon color="inherit" src={`${ASSETS_URL}/icons/icon_customers.svg`} />,
        items: [
          {
            path: `/badge/${badgeItem2}`,
            name: badgeItem2,
            badgeText: badgeItem2,
            subItems: [
              {
                path: `/badge/${badgeItem2}/${badgeItem3}`,
                name: badgeItem3,
                badgeText: badgeItem3
              }
            ]
          }
        ]
      }
    };
    const { queryByTestId } = render(
      <Provider>
        <Sidebar
          logo=""
          open="open"
          setOpen={setOpen}
          sidebarItemsMap={items}
          drawerWidthClose=""
          drawerWidthOpen=""
        />
      </Provider>
    );

    const firstItem = queryByTestId(`badge-${badgeItem1}`);
    firstItem?.click();
    const secondItem = queryByTestId(`badge-${badgeItem2}`);
    secondItem?.click();
    const thirdItem = queryByTestId(`badge-${badgeItem3}`);

    expect(firstItem?.innerHTML).toBe(badgeItem1);
    expect(secondItem?.innerHTML).toBe(badgeItem2);
    expect(thirdItem?.innerHTML).toBe(badgeItem3);
  });

  describe('Test <sidebar/> behavior on diffrent state', () => {
    it(`setOpen sould be called with open = open`, () => {
      const { queryByTestId } = render(
        <Provider>
          <Sidebar
            logo=""
            open="open"
            setOpen={setOpen}
            sidebarItemsMap={sidebarItemsMap}
            drawerWidthClose=""
            drawerWidthOpen=""
          />
        </Provider>
      );
      const elm = queryByTestId('button-drawerLeft');
      elm?.click();
      expect(setOpen).toBeCalledWith('closed');
    });
    it(`setOpen sould be called with open = closed`, () => {
      const { queryByTestId } = render(
        <Provider>
          <Sidebar
            logo=""
            open="closed"
            setOpen={setOpen}
            sidebarItemsMap={sidebarItemsMap}
            drawerWidthClose=""
            drawerWidthOpen=""
          />
        </Provider>
      );
      const elm = queryByTestId('button-drawerLeft');
      elm?.click();
      expect(setOpen).toBeCalledWith('open');
    });
    it(`setOpen sould be called with open = locked`, () => {
      const { queryByTestId } = render(
        <Provider>
          <Sidebar
            logo=""
            open="locked"
            setOpen={setOpen}
            sidebarItemsMap={sidebarItemsMap}
            drawerWidthClose=""
            drawerWidthOpen=""
          />
        </Provider>
      );
      const elm = queryByTestId('button-drawerLeft');
      elm?.click();
      expect(setOpen).toBeCalledWith('closed');
    });
  });
});
