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

afterEach(cleanup);

const defaultProps = mock<IRoleFilterProps>();
describe("RoleFilter component rendering", () => {
	it("should render role filter", () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All",
			},
			{
				name: "1",
				value: "1",
				title: "Administrator",
			},
			{
				name: "2",
				value: "2",
				title: "Editor",
			},
		];
		defaultProps.pointer = "filterRoles";
		defaultProps.filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;

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

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

describe("RoleFilter events", () => {
	it("should render check group on click", () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All",
			},
			{
				name: "1",
				value: "1",
				title: "Administrator",
			},
			{
				name: "2",
				value: "2",
				title: "Editor",
			},
		];
		defaultProps.pointer = "filterRoles";
		defaultProps.filterItems = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;

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

		const roleFilterButton = screen.getByTestId("floating-menu-button");
		expect(roleFilterButton).toBeTruthy();
		fireEvent.click(roleFilterButton);
		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",
			},
			{
				name: "1",
				value: "1",
				title: "Administrator",
			},
			{
				name: "2",
				value: "2",
				title: "Editor",
			},
		];
		defaultProps.pointer = "filterRoles";
		const onChangeMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
		defaultProps.filterItems = onChangeMock;

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

		const roleFilterButton = screen.getByTestId("floating-menu-button");
		expect(roleFilterButton).toBeTruthy();
		fireEvent.click(roleFilterButton);
		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: "1" } });
		expect(checkFieldInputs[1].checked).toBe(true);
	});

	it("should call filterItems action on change", async () => {
		defaultProps.filters = [
			{
				name: "all",
				value: "all",
				title: "All",
			},
			{
				name: "1",
				value: "1",
				title: "Administrator",
			},
			{
				name: "2",
				value: "2",
				title: "Editor",
			},
		];
		defaultProps.pointer = "filterRoles";
		const onChangeMock = jest.fn() as CalledWithMock<void, [pointer: string, filter: IQueryValue[]]>;
		defaultProps.filterItems = onChangeMock;

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

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

		expect(roleFilterButton).toBeTruthy();
		fireEvent.click(roleFilterButton);
		const checkFieldInputs = screen.queryAllByTestId("check-field-input");
		fireEvent.click(checkFieldInputs[1]);
		expect(onChangeMock).toHaveBeenCalledTimes(1);
		expect(onChangeMock).toBeCalledWith("filterRoles", [{ label: "Administrator", value: "1" }]);
	});
});
