import * as React from "react";
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
import { mock } from "jest-mock-extended";
import { ThemeProvider } from "styled-components";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";
import HourInput from "@ax/components/Fields/TimeField/HourInput";
import { act, Simulate } from "react-dom/test-utils";

afterEach(cleanup);

const defaultProps = mock<IHourInputProps>();

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

		const hourInputField = screen.getByTestId("time-field-input");
		expect(hourInputField).toBeTruthy();
	});

	it("should render component as disabled", () => {
		defaultProps.disabled = true;

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

		const hourInputField = screen.getByTestId<HTMLInputElement>("time-field-input");
		expect(hourInputField.disabled).toEqual(true);
	});
});

describe("onChange events", () => {
	it("should call onChange on change with valid time", () => {
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: string) => void>;
		defaultProps.value = "12:30";
		defaultProps.disabled = false;

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

		const input = screen.getByTestId("time-field-input");
		act(() => {
			fireEvent.change(input, { target: { value: "12:30" } });
			Simulate.change(input);
		});

		expect(onChangeMock).toHaveBeenCalledWith("12:30");
	});

	it("should call onChange on change with 24 hours time", () => {
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: string) => void>;
		defaultProps.value = "12:00";

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

		const input = screen.getByTestId("time-field-input");
		act(() => {
			fireEvent.change(input, { target: { value: "23:30" } });
			Simulate.change(input);
		});

		expect(onChangeMock).toHaveBeenCalledWith("12:30");
	});

	it("should call onChange on change with 24 hours time", () => {
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: string) => void>;
		defaultProps.value = "12:00";

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

		const input = screen.getByTestId("time-field-input");
		act(() => {
			fireEvent.change(input, { target: { value: "23:30" } });
			Simulate.change(input);
		});

		expect(onChangeMock).toHaveBeenCalledWith("12:30");
	});

	it("should call onChange on change with more than 12 hours", () => {
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: string) => void>;
		defaultProps.value = "12:00";

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

		const input = screen.getByTestId("time-field-input");
		act(() => {
			fireEvent.change(input, { target: { value: "13:30" } });
			Simulate.change(input);
		});

		expect(onChangeMock).toHaveBeenCalledWith("12:30");
	});

	it("should call onChange on change with more than 59 minutes", () => {
		const onChangeMock = defaultProps.onChange as jest.MockedFunction<(value: string) => void>;
		defaultProps.value = "12:30";

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

		const input = screen.getByTestId("time-field-input");
		act(() => {
			fireEvent.change(input, { target: { value: "10:72" } });
			Simulate.change(input);
		});

		expect(onChangeMock).toHaveBeenCalledWith("10:30");
	});
});

interface IHourInputProps {
	value: string;
	onChange: (value: string) => void;
	disabled?: boolean;
}
