import React from "react";

import { ThemeProvider } from "styled-components";
import { render, screen, cleanup, fireEvent, act } from "@testing-library/react";
import "@testing-library/jest-dom";
import { mock } from "jest-mock-extended";

import { parseTheme } from "@ax/helpers";

import Tooltip, { ITooltipProps } from "@ax/components/Tooltip";
import { Icon } from "@ax/components";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

const defaultProps = mock<ITooltipProps>();

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

		const tooltipComponent = screen.getByTestId("tooltip-component");
		const tipComponent = screen.getByTestId("tip-component");

		expect(tooltipComponent).toBeTruthy();
		expect(tipComponent).toBeTruthy();
	});

	it("should not render the component", () => {
		defaultProps.content = undefined;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tooltip {...defaultProps} />
			</ThemeProvider>,
		);

		const tooltipComponent = screen.queryByTestId("tooltip-component");
		expect(tooltipComponent).not.toBeTruthy();
	});
});

describe("Tooltip events triggering", () => {
	it("should render the component and Tip Component is still visible when doing click", () => {
		jest.useFakeTimers();
		defaultProps.content = "content";
		defaultProps.children = <Icon name="modified" size="16px" />;

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

		const tooltipComponent = screen.getByTestId("tooltip-component");
		const tipComponent = screen.queryByText("content");

		defaultProps.hideOnClick = false;
		rerender(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tooltip {...defaultProps} />
			</ThemeProvider>,
		);
		expect(tipComponent).not.toBeVisible();

		act(() => {
			// over the tooltip
			fireEvent.mouseEnter(tooltipComponent);

			rerender(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<Tooltip {...defaultProps} />
				</ThemeProvider>,
			);
			jest.runAllTimers();
		});

		expect(tipComponent).toBeVisible();

		act(() => {
			// click and change the clicked value
			fireEvent.mouseDown(tooltipComponent);

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

			jest.runAllTimers();
		});
		expect(tipComponent).toBeVisible();
	});

	it("should render the component and change visibility of Tip Component when click", () => {
		jest.useFakeTimers();
		defaultProps.content = "content";
		defaultProps.children = <Icon name="modified" size="16px" />;

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

		const tooltipComponent = screen.getByTestId("tooltip-component");
		const tipComponent = screen.queryByText("content");

		defaultProps.hideOnClick = true;
		rerender(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tooltip {...defaultProps} />
			</ThemeProvider>,
		);
		expect(tipComponent).not.toBeVisible();

		act(() => {
			// over the tooltip
			fireEvent.mouseEnter(tooltipComponent);

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

			jest.runAllTimers();
		});

		expect(tipComponent).toBeVisible();

		act(() => {
			fireEvent.mouseDown(tooltipComponent);

			rerender(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<Tooltip {...defaultProps} />
				</ThemeProvider>,
			);
		});
		fireEvent.mouseEnter(tooltipComponent);
		fireEvent.mouseDown(document);

		expect(tooltipComponent).toBeTruthy();
		expect(tipComponent).not.toBeVisible();
	});
});
