import React from "react";
import "@testing-library/jest-dom";
import ColorPicker, { IProps } from "@ax/components/Fields/ColorPicker";
import { ThemeProvider } from "styled-components";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
import { mock } from "jest-mock-extended";

afterEach(cleanup);

const defaultProps = mock<IProps>();

describe("ColorPicker component rendering", () => {
	test("should render the component ColorPicker", () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);
		expect(screen.getByTestId("color-picker-wrapper")).toBeTruthy();
	});

	test("should render the Picker", () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		defaultProps.error = true;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);
		const inputActionComponent = screen.getByTestId("icon-action-component");
		expect(inputActionComponent).toBeTruthy();
		fireEvent.click(inputActionComponent);
		expect(screen.findByTestId("picker-wrapper")).toBeTruthy();
	});
});

describe("ColorPicker events", () => {
	test("should trigger the onChange", () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		defaultProps.colors = ["#000000", "#d9e3f0", "#f47373", "#697689"];
		defaultProps.isThemePalette = false;
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(newColor: string) => void>;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);
		const inputComponent = screen.getByTestId("input-picker-wrapper");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: 555 } });
		expect(onChangeMock).not.toBeCalled();
		fireEvent.change(inputComponent, { target: { value: "#ffffff" } });
		expect(onChangeMock).toBeCalledWith("#ffffff");
		fireEvent.change(inputComponent, { target: { value: "#fff" } });
		expect(onChangeMock).toBeCalledWith("#ffffff");
	});

	test("should trigger the onChange", () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		const handleValidationMock = defaultProps.handleValidation as jest.MockedFunction<
			(value: string, validators: Record<string, unknown>) => void
		>;
		defaultProps.error = true;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);
		const inputComponent = screen.getByTestId("input-picker-wrapper");
		expect(inputComponent).toBeTruthy();
		fireEvent.change(inputComponent, { target: { value: "#fff" } });
		expect(handleValidationMock).toBeCalled();
	});

	test("should trigger the onChange of the Picker", async () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		defaultProps.error = true;
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(newColor: string) => void>;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);

		const inputActionComponent = screen.getByTestId("icon-action-component");
		expect(inputActionComponent).toBeTruthy();
		fireEvent.click(inputActionComponent);
		const inputPicker = await screen.findByTestId("input-picker");
		expect(inputPicker).toBeTruthy();
		fireEvent.change(inputPicker, { target: { value: "#fff" } });
		expect(onChangeMock).toBeCalled();
	});

	test("should trigger the onChange of the Picker with color", async () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		defaultProps.error = true;
		defaultProps.colors = ["#fff", "#000"];
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(newColor: string) => void>;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);

		const inputActionComponent = screen.getByTestId("icon-action-component");
		expect(inputActionComponent).toBeTruthy();
		fireEvent.click(inputActionComponent);
		const inputPicker = await screen.findByTestId("input-picker");
		expect(inputPicker).toBeTruthy();
		fireEvent.change(inputPicker, { target: { value: "#fff" } });
		expect(onChangeMock).toBeCalled();
	});

	test("should not pass colors to picker", async () => {
		defaultProps.value = "#000000";
		defaultProps.theme = "default";
		defaultProps.error = true;
		defaultProps.colors = [
			{ color: "#f0f0f0", theme: "default" },
			{ color: "#fff", theme: "cms-default" },
		];

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

		const inputActionComponent = screen.getByTestId("icon-action-component");
		expect(inputActionComponent).toBeTruthy();
		fireEvent.click(inputActionComponent);
		const gridItem = await screen.findAllByTestId("grid-item");
		// is getting the default colors
		expect(gridItem).toHaveLength(9);
	});

	test("should pass colors to picker", async () => {
		defaultProps.value = "#000000";
		defaultProps.theme = "default";
		defaultProps.error = true;
		defaultProps.colors = [
			{ options: ["#f0f0f0"], theme: "default" },
			{ color: "#fff", theme: "cms-default" },
		];

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

		const inputActionComponent = screen.getByTestId("icon-action-component");
		expect(inputActionComponent).toBeTruthy();
		fireEvent.click(inputActionComponent);
		const gridItem = await screen.findAllByTestId("grid-item");
		// it's getting the color passed
		expect(gridItem).toHaveLength(1);
	});

	test("should trigger the handleOnBlur", async () => {
		defaultProps.value = "#000000";
		defaultProps.theme = parseTheme(globalTheme);
		const handleValidationMock = defaultProps.handleValidation as jest.MockedFunction<
			(value: string, validators: Record<string, unknown>) => void
		>;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ColorPicker {...defaultProps} />
			</ThemeProvider>,
		);
		const inputComponent = screen.getByTestId("input-picker-wrapper");
		expect(inputComponent).toBeTruthy();
		fireEvent.blur(inputComponent, { target: { value: "#fff" } });
		expect(handleValidationMock).toBeCalled();
	});
});
