import * as React from "react";

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

import Toast, { IToastProps } from "@ax/components/Toast";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

jest.mock("react-router-dom", () => ({
	...jest.requireActual("react-router-dom"),
	useLocation: () => ({
		pathname: "localhost:3000/example/path",
	}),
}));

const defaultProps = mock<IToastProps>();

describe("Toast component rendering", () => {
	jest.useFakeTimers();
	jest.spyOn(global, "setTimeout");

	it("should render the component", () => {
		defaultProps.message = "1 module copied to clipboard";

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

		const toastWrapper = screen.getByTestId("toast-wrapper");
		expect(toastWrapper).toBeTruthy();
	});

	it("should render the component's message", () => {
		defaultProps.message = "1 module copied to clipboard";

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

		const toastMessage = screen.getByTestId("toast-message");
		expect(toastMessage.textContent).toEqual("1 module copied to clipboard");
	});

	it("should not render the undo button when no action", () => {
		defaultProps.message = "1 module copied to clipboard";

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

		const button = screen.queryByTestId("button-line-inverse");
		expect(button).toBeFalsy();
	});
});

describe("Toast component events", () => {
	it("should render the undo button when action", () => {
		defaultProps.message = "1 module copied to clipboard";
		defaultProps.action = jest.fn();

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

		const button = screen.getByTestId("button-line-inverse");
		expect(button).toBeTruthy();
	});

	it("should change visibility after 5000 ms", async () => {
		defaultProps.message = "1 module copied to clipboard";

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

		expect(setTimeout).toHaveBeenCalled();
		expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 5000);
	});

	it("should contain closing animation class on click close button", async () => {
		defaultProps.message = "1 module copied to clipboard";

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

		const toastWrapper = screen.getByTestId("toast-wrapper");
		const closeButton = screen.getByTestId("icon-action-component");
		expect(closeButton).toBeTruthy();
		fireEvent.click(closeButton);
		expect(toastWrapper.classList.contains("close-animation")).toBeTruthy();
	});
});
