import * as React from "react";

import { ThemeProvider } from "styled-components";
import { CalledWithMock, mock } from "jest-mock-extended";

import { render, screen, cleanup, fireEvent } from "@testing-library/react";

import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";
import UsersFilter, { IUsersFilterProps } from "@ax/components/TableFilters/UsersFilter";
import { IQueryValue } from "@ax/types";

afterEach(cleanup);
const defaultProps = mock<IUsersFilterProps>();
describe("UsersFilter component rendering", () => {
	it("should render users filter", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: true };

		defaultProps.sortItems = onClickMock;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const usersFilter = screen.getByTestId("users-filter-header");
		expect(usersFilter).toBeTruthy();
		expect(usersFilter.textContent).toEqual("Users");
	});

	it("should render interactive arrow if not filter selected", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: false };
		defaultProps.sortItems = onClickMock;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const interactiveArrow = screen.getByTestId("users-filter-interactive-arrow");
		expect(interactiveArrow).toBeTruthy();
	});

	it("should not render interactive arrow if filter selected", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: false, sortedByTitle: false, sortedByUsers: true };
		defaultProps.sortItems = onClickMock;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const interactiveArrow = screen.queryByTestId("users-filter-interactive-arrow");
		expect(interactiveArrow).toBeFalsy();
	});

	it("should render FullArrowUp icon if is filtered by ascending users", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: true };
		defaultProps.sortItems = onClickMock;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const arrowIcon = screen.getByTestId("icon-component-fullarrowup");
		expect(arrowIcon).toBeTruthy();
	});
});

describe("UsersFilter events", () => {
	it("should render check group on click", () => {
		const onClickMock = jest.fn();
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: true };
		defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const usersFilterButton = screen.getByTestId("floating-menu-button");
		expect(usersFilterButton).toBeTruthy();
		fireEvent.click(usersFilterButton);
		const floatingMenu = screen.getByTestId("floating-menu");
		expect(floatingMenu).toBeTruthy();
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		expect(listItems[0].textContent).toEqual("Ascendent");
		expect(listItems[1].textContent).toEqual("Descendent");
	});

	it("should call filterItems with isAscending on click 'Ascendent' option", async () => {
		const onClickMock = jest.fn();
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: true };
		defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const usersFilterButton = screen.getByTestId("floating-menu-button");

		expect(usersFilterButton).toBeTruthy();
		fireEvent.click(usersFilterButton);
		const listItems = screen.getAllByTestId("list-item");

		fireEvent.click(listItems[0]);
		expect(onClickMock).toHaveBeenCalledTimes(1);
		const isAscending = true;
		expect(onClickMock).toBeCalledWith([{ label: "users", value: "users" }], isAscending);
	});

	it("should call filterItems with isAscending false on click 'Descendent' option", async () => {
		const onClickMock = jest.fn();
		defaultProps.sortedState = { isAscending: true, sortedByTitle: false, sortedByUsers: true };
		defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<UsersFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const usersFilterButton = screen.getByTestId("floating-menu-button");

		expect(usersFilterButton).toBeTruthy();
		fireEvent.click(usersFilterButton);
		const listItems = screen.getAllByTestId("list-item");

		fireEvent.click(listItems[1]);
		expect(onClickMock).toHaveBeenCalledTimes(1);
		const isAscending = false;
		expect(onClickMock).toBeCalledWith([{ label: "users", value: "users" }], isAscending);
	});
});
