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 TypeFilter, { ITypeFilterProps } from "@ax/components/TableFilters/TypeFilter";
import globalTheme from "@ax/themes/theme.json";
import { parseTheme } from "@ax/helpers";
import { IQueryValue } from "@ax/types";

afterEach(cleanup);

const defaultProps = mock<ITypeFilterProps>();
describe("TypeFilter component rendering", () => {
	it("should render type filter", () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All content",
			},
			{
				name: "unique",
				value: "unique",
				title: "Basic templates",
			},
			{
				name: "structuredData",
				value: "structuredData",
				title: "Content types",
			},
		];
		defaultProps.pointer = "type";
		defaultProps.filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;

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

		const typeFilter = screen.getByTestId("floating-menu");
		expect(typeFilter).toBeTruthy();
		expect(typeFilter.textContent).toEqual("Types");
	});
});

describe("TypeFilter events", () => {
	it("should render check group on click", () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All content",
			},
			{
				name: "unique",
				value: "unique",
				title: "Basic templates",
			},
			{
				name: "structuredData",
				value: "structuredData",
				title: "Content types",
			},
		];
		defaultProps.pointer = "type";
		defaultProps.filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;

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

		const typeFilterButton = screen.getByTestId("floating-menu-button");
		expect(typeFilterButton).toBeTruthy();
		fireEvent.click(typeFilterButton);
		const floatingMenu = screen.getByTestId("floating-menu");
		expect(floatingMenu).toBeTruthy();
		const checkGroupFieldGroup = screen.getByTestId("check-group-field-group");
		expect(checkGroupFieldGroup).toBeTruthy();
		const checkFieldLabels = screen.getAllByTestId("check-field-label");
		expect(checkFieldLabels).toHaveLength(3);
	});

	it("should check option on click", () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All content",
			},
			{
				name: "unique",
				value: "unique",
				title: "Basic templates",
			},
			{
				name: "structuredData",
				value: "structuredData",
				title: "Content types",
			},
		];
		defaultProps.pointer = "type";
		const onChangeMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
		defaultProps.filterItems = onChangeMock;

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

		const typeFilterButton = screen.getByTestId("floating-menu-button");
		expect(typeFilterButton).toBeTruthy();
		fireEvent.click(typeFilterButton);
		const floatingMenu = screen.getByTestId("floating-menu");
		expect(floatingMenu).toBeTruthy();
		const checkGroupFieldGroup = screen.getByTestId("check-group-field-group");
		expect(checkGroupFieldGroup).toBeTruthy();
		const checkFieldInputs = screen.getAllByTestId<HTMLInputElement>("check-field-input");
		expect(checkFieldInputs).toHaveLength(3);
		fireEvent.change(checkFieldInputs[1], { target: { checked: true, value: "unique" } });
		expect(checkFieldInputs[1].checked).toBe(true);
	});

	it("should call filterItems action on change", async () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All content",
			},
			{
				name: "unique",
				value: "unique",
				title: "Basic templates",
			},
			{
				name: "structuredData",
				value: "structuredData",
				title: "Content types",
			},
		];
		defaultProps.pointer = "type";
		const onChangeMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
		defaultProps.filterItems = onChangeMock;

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

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

		expect(typeFilterButton).toBeTruthy();
		fireEvent.click(typeFilterButton);
		const checkFieldInputs = screen.queryAllByTestId("check-field-input");
		fireEvent.click(checkFieldInputs[1]);
		expect(onChangeMock).toHaveBeenCalledTimes(1);
		expect(onChangeMock).toBeCalledWith("type", [{ label: "Basic templates", value: "unique" }]);
	});
});
