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

afterEach(cleanup);

const defaultProps = mock<INumberFieldProps>();
const user = userEvent.setup();

describe("NumberField component rendering", () => {
	it("should render the component", () => {
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<NumberField {...defaultProps} />
			</ThemeProvider>,
		);

		const conditionalFieldContent = screen.getByTestId("conditional-field-wrapper");

		expect(conditionalFieldContent).toBeTruthy();
	});
});

describe("onClick events", () => {
	it("should call onChange when clicking arrow up", () => {
		const onChange = jest.fn();

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

		const arrowUp = screen.getByTestId("arrow-up");
		fireEvent.click(arrowUp);
		expect(onChange).toHaveBeenCalledWith(1);
	});

	it("should call onChange when clicking arrow down", () => {
		defaultProps.value = 2;
		defaultProps.min = 1;
		const onChange = jest.fn();

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

		const arrowDown = screen.getByTestId("arrow-down");
		fireEvent.click(arrowDown);
		expect(onChange).toHaveBeenCalledWith(1);
		fireEvent.click(arrowDown);
		expect(onChange).toHaveBeenCalledWith(1);
	});
});

describe("onBlur events", () => {
	it("should call handleValidation on blur", () => {
		const handleValidation = jest.fn();
		const onBlur = jest.fn();

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

		const input = screen.getByTestId("input");
		fireEvent.blur(input);
		expect(handleValidation).toHaveBeenCalled();
	});
});

describe("onChange events", () => {
	it("should call onChange on change", () => {
		defaultProps.max = 7;
		defaultProps.error = true;
		const onChange = jest.fn();
		const handleValidation = jest.fn();

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

		const input = screen.getByTestId("input");
		fireEvent.change(input, { target: { value: 5 } });
		expect(onChange).toHaveBeenCalledWith(5);
		expect(handleValidation).toHaveBeenCalled();
	});

	it("should call onChange with undefined", async () => {
		defaultProps.value = undefined;
		const onChange = jest.fn();

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

		const input = screen.getByTestId("input");
		input.focus();
		await user.keyboard("{4}{Backspace}");
		expect(onChange).toHaveBeenCalledWith(undefined);
	});
});
