import * as React from "react";

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

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

afterEach(cleanup);

describe("Notification component rendering", () => {
	it("should render the success notification", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
		};

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

		const notificationWrapper = screen.getByTestId("notification-wrapper");
		const successIcon = screen.getByTestId("success-icon");
		expect(notificationWrapper).toBeTruthy();
		expect(successIcon).toBeTruthy();
	});

	it("should render the error notification", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "error",
		};

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

		const notificationWrapper = screen.getByTestId("notification-wrapper");
		const alertIcon = screen.getByTestId("alert-icon");
		expect(notificationWrapper).toBeTruthy();
		expect(alertIcon).toBeTruthy();
	});

	it("should render the warning notification", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "warning",
		};

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

		const notificationWrapper = screen.getByTestId("notification-wrapper");
		const warningIcon = screen.getByTestId("warning-icon");
		expect(notificationWrapper).toBeTruthy();
		expect(warningIcon).toBeTruthy();
	});

	it("should render the close button", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
		};

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

		const closeButton = screen.getByTestId("close-button");
		expect(closeButton).toBeTruthy();
	});

	it("should not render the close button", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
			closeButton: false,
		};

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

		const closeButton = screen.queryByTestId("close-button");
		expect(closeButton).toBeFalsy();
	});

	it("should render the action button with no actionsBelow", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
			btnText: "Action",
		};

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

		const actionButton = screen.getByTestId("action-button");
		expect(actionButton).toBeTruthy();
	});

	it("should render the action button with actionsBelow", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
			btnText: "Action",
			actionsBelow: true,
		};

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

		const actionButton = screen.getByTestId("action-button");
		expect(actionButton).toBeTruthy();
	});
});

describe("Notification component with subnotifications", () => {
	it("should render the subnotifications open button", () => {
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "error",
			subErrors: [
				{ id: 1, error: "SubError 1" },
				{ id: 2, error: "SubError 2" },
				{ id: 3, error: "Suberror 3" },
			],
		};

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

		const suberrorsButton = screen.getByTestId("suberrors-button");
		expect(suberrorsButton).toBeTruthy();
		fireEvent.click(suberrorsButton);
		const subnotifications = screen.getAllByTestId("subnotification-wrapper");
		expect(subnotifications).toHaveLength(3);
	});
});

describe("Notification component events", () => {
	it("should call onClick on action button click", () => {
		const onClickMock = jest.fn();
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
			btnText: "Action",
			onClick: onClickMock,
		};

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

		const actionButton = screen.getByTestId("action-button");
		expect(actionButton).toBeTruthy();
		fireEvent.click(actionButton);
		expect(onClickMock).toBeCalledTimes(1);
	});

	it("should call resetError on close and hide notification", () => {
		const resetErrorMock = jest.fn();
		const defaultProps: INotificationProps = {
			text: "Notification text",
			type: "success",
			resetError: resetErrorMock,
		};

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

		const closeButton = screen.getByTestId("close-button");
		expect(closeButton).toBeTruthy();
		fireEvent.click(closeButton);
		expect(resetErrorMock).toBeCalledTimes(1);
		const notificationWrapper = screen.getByTestId("notification-wrapper");
		expect(notificationWrapper).not.toBeVisible();
	});
});
