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 NameFilter, { INameFilterProps } from "@ax/components/TableFilters/NameFilter";
import { IQueryValue } from "@ax/types";

afterEach(cleanup);
const defaultProps = mock<INameFilterProps>();
describe("NameFilter component rendering", () => {
	it("should render name filter", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false };
		defaultProps.sortItems = onClickMock;
		defaultProps.urlSorting = false;

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

		const nameFilter = screen.getByTestId("name-filter-header");
		expect(nameFilter).toBeTruthy();
		expect(nameFilter.textContent).toEqual("Name");
	});

	it("should render URL on title if it is URL sorting", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: true, sortedByTitle: true };
		defaultProps.sortItems = onClickMock;
		defaultProps.urlSorting = true;

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

		const nameFilter = screen.getByTestId("name-filter-header");
		expect(nameFilter).toBeTruthy();
		expect(nameFilter.textContent).toEqual("Name & URL");
	});

	it("should render URL sorting option if it is URL sorting", () => {
		const onClickMock = jest.fn() as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		defaultProps.sortedState = { isAscending: true, sortedByTitle: true };
		defaultProps.sortItems = onClickMock;
		defaultProps.urlSorting = true;

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

		const nameFilterButton = screen.getByTestId("floating-menu-button");
		expect(nameFilterButton).toBeTruthy();
		fireEvent.click(nameFilterButton);
		const floatingMenu = screen.getByTestId("floating-menu");
		expect(floatingMenu).toBeTruthy();
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(3);
	});

	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: false, sortedByDate: false, sortedByTitle: false, sortedByURL: false };
		defaultProps.sortItems = onClickMock;
		defaultProps.urlSorting = false;

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

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

	it("should not 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: false, sortedByTitle: true };
		defaultProps.sortItems = onClickMock;
		defaultProps.urlSorting = false;

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

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

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

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

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

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

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

		const nameFilterButton = screen.getByTestId("floating-menu-button");
		expect(nameFilterButton).toBeTruthy();
		fireEvent.click(nameFilterButton);
		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: false, sortedByDate: false };
		defaultProps.sortItems = onClickMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);

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

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

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

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

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

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

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

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

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