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

afterEach(cleanup);
const defaultProps = mock<IStatusFilterProps>();
describe("StatusFilter component rendering", () => {
	it("should render date 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.isStructuredData = false;

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

		const statusFilter = screen.getByTestId("status-filter-header");
		expect(statusFilter).toBeTruthy();
		expect(statusFilter.textContent).toEqual("Last update");
	});

	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.isStructuredData = false;

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

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

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

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

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

describe("StatusFilter 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)}>
				<StatusFilter {...defaultProps} />
			</ThemeProvider>,
		);

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

	it("should call sortItems function with 'modified, true' as param when it's not structured data and is ascending", 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)}>
				<StatusFilter {...defaultProps} />
			</ThemeProvider>,
		);

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

		expect(statusFilterButton).toBeTruthy();
		fireEvent.click(statusFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		expect(listItems[0].textContent).toEqual("Most recent");
		expect(listItems[1].textContent).toEqual("Oldest");

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

	it("should call sortItems function with 'date, true' as param when it's not structured data and is asceding", 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);
		defaultProps.isStructuredData = true;

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

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

		expect(statusFilterButton).toBeTruthy();
		fireEvent.click(statusFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		expect(listItems[0].textContent).toEqual("Most recent");
		expect(listItems[1].textContent).toEqual("Oldest");

		fireEvent.click(listItems[1]);
		expect(onClickMock).toHaveBeenCalledTimes(1);
		expect(onClickMock).toBeCalledWith([{ label: "date", value: "date" }], true);
	});

	it("should call sortItems function with 'modified, false' as param when it's not structured data and is not ascending", 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);
		defaultProps.isStructuredData = false;

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

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

		expect(statusFilterButton).toBeTruthy();
		fireEvent.click(statusFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		expect(listItems[0].textContent).toEqual("Most recent");
		expect(listItems[1].textContent).toEqual("Oldest");

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

	it("should call sortItems function with 'date, false' as param when it's not structured data and is not asceding", 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);
		defaultProps.isStructuredData = true;

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

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

		expect(statusFilterButton).toBeTruthy();
		fireEvent.click(statusFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		expect(listItems[0].textContent).toEqual("Most recent");
		expect(listItems[1].textContent).toEqual("Oldest");

		fireEvent.click(listItems[0]);
		expect(onClickMock).toHaveBeenCalledTimes(1);
		expect(onClickMock).toBeCalledWith([{ label: "date", value: "date" }], false);
	});
});
