import * as React from "react";
import { ThemeProvider } from "styled-components";
import { render, cleanup, screen, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom";

import { parseTheme } from "@ax/helpers";
import ActionMenu, { IActionMenuProps } from "@ax/components/ActionMenu";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

describe("Action menu component rendering", () => {
	it("should render the component with options hidden", () => {
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: jest.fn(),
				},
				{
					label: "Option 2",
					icon: "active",
					action: jest.fn(),
				},
			],
		};

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

		const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
		expect(actionMenuWrapper).toBeTruthy();
		const menuItems = screen.queryAllByTestId("action-menu-item");
		expect(menuItems.length).toBe(0);
	});
});

describe("Action menu events", () => {
	it("should show the component with 2 options on icon click", () => {
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: jest.fn(),
				},
				{
					label: "Option 2",
					icon: "active",
					action: jest.fn(),
				},
			],
		};

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

		const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
		expect(actionMenuWrapper).toBeTruthy();
		const iconAction = screen.getByTestId("icon-action-component");
		expect(iconAction).toBeTruthy();
		fireEvent.click(iconAction);

		const menuItems = screen.getAllByTestId("action-menu-item");
		expect(menuItems.length).toBe(2);
	});

	it("should show the component with option with helptext", () => {
		const helpText = "this is the helptext";
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: jest.fn(),
					helpText,
				},
			],
		};

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

		const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
		expect(actionMenuWrapper).toBeTruthy();
		const iconAction = screen.getByTestId("icon-action-component");
		expect(iconAction).toBeTruthy();
		fireEvent.click(iconAction);

		const helpTextComponent = screen.getByText(helpText);
		expect(helpTextComponent).toBeTruthy();
	});

	it("should show the component with option with original class", () => {
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: jest.fn(),
					color: true,
				},
				{
					label: "Option 2",
					icon: "active",
					action: jest.fn(),
				},
			],
		};

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

		const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
		expect(actionMenuWrapper).toBeTruthy();
		const iconAction = screen.getByTestId("icon-action-component");
		expect(iconAction).toBeTruthy();
		fireEvent.click(iconAction);
		const menuItems = screen.getAllByTestId("action-menu-item");

		expect(menuItems[0]).toHaveClass("original");
		expect(menuItems[1]).not.toHaveClass("original");
	});

	it("should hide the component on second icon click", () => {
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: jest.fn(),
				},
				{
					label: "Option 2",
					icon: "active",
					action: jest.fn(),
				},
			],
		};

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

		const actionMenuWrapper = screen.getByTestId("action-menu-wrapper");
		expect(actionMenuWrapper).toBeTruthy();
		const iconAction = screen.getByTestId("icon-action-component");
		expect(iconAction).toBeTruthy();
		fireEvent.click(iconAction);

		const menuItems = screen.getAllByTestId("action-menu-item");
		expect(menuItems.length).toBe(2);

		fireEvent.click(iconAction);

		const menuItems2 = screen.queryAllByTestId("action-menu-item");
		expect(menuItems2.length).toBe(0);
	});

	it("should call action on item click and hide component", () => {
		const actionMock = jest.fn();
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: actionMock,
				},
			],
		};

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

		const iconAction = screen.getByTestId("icon-action-component");
		fireEvent.click(iconAction);

		const menuItems = screen.getAllByTestId("action-menu-item");
		expect(menuItems.length).toBe(1);
		fireEvent.click(menuItems[0]);

		expect(actionMock).toBeCalledTimes(1);

		const menuItems2 = screen.queryAllByTestId("action-menu-item");
		expect(menuItems2.length).toBe(0);
	});

	it("should show disabled item", () => {
		const actionMock = jest.fn();
		const defaultProps: IActionMenuProps = {
			icon: "more",
			options: [
				{
					label: "Option 1",
					icon: "modified",
					action: actionMock,
					disabled: true,
				},
				{
					label: "Option 2",
					icon: "active",
					action: jest.fn(),
				},
			],
		};

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

		const iconAction = screen.getByTestId("icon-action-component");
		fireEvent.click(iconAction);

		const menuItems = screen.getAllByTestId("action-menu-item");
		expect(menuItems.length).toBe(2);

		expect(menuItems[0]).toHaveAttribute("disabled");
		expect(menuItems[1]).not.toHaveAttribute("disabled");
	});
});
