import React from "react";
import TagsField from "@ax/components/Fields/TagsField";
import { ThemeProvider } from "styled-components";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";
import { render, screen, within, cleanup, fireEvent } from "@testing-library/react";

afterEach(cleanup);

const props = {
	value: [],
	onChange: jest.fn(),
};

describe("TagsField component", () => {
	test("should render the component", () => {
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<TagsField {...props} />
			</ThemeProvider>,
		);

		const tagsFieldWrapper = screen.getAllByTestId("tag-field-wrapper");
		expect(tagsFieldWrapper).toBeTruthy();
		expect(tagsFieldWrapper).toHaveLength(1);

		const tagsFieldInput = screen.getAllByTestId("tag-field-input");
		expect(tagsFieldInput).toBeTruthy();
		expect(tagsFieldInput).toHaveLength(1);
	});

	test("should render the tags if have values", () => {
		const defaultProps = {
			value: ["one", "two"],
			onChange: jest.fn(),
		};

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

		const tagsFieldWrapper = screen.getByTestId("tag-field-wrapper");
		expect(tagsFieldWrapper).toBeTruthy();

		const tagsFieldInput = screen.getByTestId("tag-field-input");
		expect(tagsFieldInput).toBeTruthy();

		const tagRendered = within(tagsFieldWrapper).getAllByTestId("delete-icon-wrapper");
		expect(tagRendered).toHaveLength(2);

		const tagComponent = screen.getByTestId("tag-field-wrapper");
		expect(tagComponent.textContent).toBe("onetwo");
	});
});

describe("TagsField events", () => {
	test("should call the value when call onchange", () => {
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<TagsField {...props} />
			</ThemeProvider>,
		);
		const TagsFieldInput = screen.getByTestId<HTMLInputElement>("tag-field-input");

		fireEvent.change(TagsFieldInput, { target: { value: "test" } });
		expect(TagsFieldInput.value).toBe("test");
	});

	test("should add new value on keyDown if it's not in array", () => {
		const onChange = jest.fn();
		const defaultProps = {
			value: [],
			onChange,
		};
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<TagsField {...defaultProps} />
			</ThemeProvider>,
		);

		const tagsFieldInput = screen.getByTestId<HTMLInputElement>("tag-field-input");
		fireEvent.input(tagsFieldInput, { target: { value: "test" } });
		fireEvent.keyDown(tagsFieldInput, { key: "Enter", code: "Enter", charCode: 13 });
		expect(onChange).toHaveBeenCalledWith(["test"]);
	});
	test("shouldn't add new value on keyDown if it's in array", () => {
		const onChange = jest.fn();
		const defaultProps = {
			value: ["test"],
			onChange,
		};
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<TagsField {...defaultProps} />
			</ThemeProvider>,
		);

		const tagsFieldInput = screen.getByTestId<HTMLInputElement>("tag-field-input");
		fireEvent.input(tagsFieldInput, { target: { value: "test" } });
		fireEvent.keyDown(tagsFieldInput, { key: "Enter", code: "Enter", charCode: 13 });
		expect(onChange).toBeCalledTimes(0);
	});
	test("should delete value from array", () => {
		const onChange = jest.fn();
		const defaultProps = {
			value: ["one", "two"],
			onChange,
		};

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

		const tagsFieldWrapper = screen.getByTestId("tag-field-wrapper");
		const tagRendered = within(tagsFieldWrapper).getAllByTestId("delete-icon-wrapper");
		expect(tagRendered).toHaveLength(2);
		fireEvent.click(tagRendered[0], 0);
		expect(onChange).toBeCalledTimes(1);
	});
	test("should call the focus function", () => {
		// we can check if the focus function is been called
		const useRefSpy = jest.spyOn(React, "useRef").mockReturnValueOnce({ current: { focus: jest.fn() } });
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<TagsField {...props} />
			</ThemeProvider>,
		);
		const tagsFieldWrapper = screen.getByTestId("tag-field-wrapper");
		fireEvent.click(tagsFieldWrapper);
		expect(useRefSpy).toBeCalledTimes(1);
	});
});
