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

afterEach(cleanup);
const defaultProps = mock<IDateFilterProps>();
describe("DateFilter component rendering", () => {
	it("should render date filter", () => {
		const sortItemsMock = jest.fn();
		defaultProps.sortedState = { isAscending: false, sortedByDate: false };
		defaultProps.sortItems = sortItemsMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<DateFilter {...defaultProps} />
			</ThemeProvider>,
		);

		const dateFilter = screen.getByTestId("date-filter");
		expect(dateFilter).toBeTruthy();
		expect(dateFilter.textContent).toEqual("Date");
	});

	it("should render interactive arrow if not filter selected", () => {
		const sortItemsMock = jest.fn();
		defaultProps.sortedState = { isAscending: false, sortedByDate: false };
		defaultProps.sortItems = sortItemsMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<DateFilter {...defaultProps} />
			</ThemeProvider>,
		);

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

	it("should not render interactive arrow if filter selected", () => {
		const sortItemsMock = jest.fn();
		defaultProps.sortedState = { isAscending: false, sortedByDate: true };
		defaultProps.sortItems = sortItemsMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<DateFilter {...defaultProps} />
			</ThemeProvider>,
		);

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

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

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

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

describe("DateFilter events", () => {
	it("should render check group on click floating menu", () => {
		const sortItemsMock = jest.fn();
		defaultProps.sortedState = { isAscending: false, sortedByDate: false };
		defaultProps.sortItems = sortItemsMock as CalledWithMock<any, [orderPointer: IQueryValue[], isAscendent: boolean]> &
			((orderPointer: IQueryValue[], isAscendent: boolean) => any);
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<DateFilter {...defaultProps} />
			</ThemeProvider>,
		);

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

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

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

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

		expect(dateFilterButton).toBeTruthy();
		fireEvent.click(dateFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		expect(listItems).toHaveLength(2);
		fireEvent.click(listItems[0]);
		expect(sortItemsMock).toHaveBeenCalledTimes(1);
		const isAscending = false;
		expect(sortItemsMock).toBeCalledWith([{ label: "date", value: "date" }], isAscending);
	});

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

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

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

		expect(dateFilterButton).toBeTruthy();
		fireEvent.click(dateFilterButton);
		const listItems = screen.getAllByTestId("list-item");
		fireEvent.click(listItems[1]);
		expect(sortItemsMock).toHaveBeenCalledTimes(1);
		const isAscending = true;
		expect(sortItemsMock).toBeCalledWith([{ label: "date", value: "date" }], isAscending);
	});
});
