import * as React from "react";

import "jest-styled-components";
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 globalTheme from "@ax/themes/theme.json";
import Tabs, { ITabsProps } from "@ax/components/Tabs";

afterEach(cleanup);

const defaultProps = mock<ITabsProps>();

describe("Tabs component rendering", () => {
	it("should render tabs", () => {
		defaultProps.tabs = ["tab1", "tab2"];
		defaultProps.active = "tab1";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

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

		const tabsRow = screen.getByTestId("tabs-row");
		const tabs = screen.getAllByTestId("tab");

		expect(tabsRow).toBeTruthy();
		expect(tabs.length).toEqual(2);
	});

	it("should render an empty tabs row when no tabs or icons", () => {
		defaultProps.tabs = undefined;
		defaultProps.icons = undefined;
		defaultProps.active = "tab1";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

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

		const emptyTabsRow = screen.getByTestId("empty-tabs-row");

		expect(emptyTabsRow).toBeTruthy();
	});

	it("should call set selected tab action on click", async () => {
		defaultProps.tabs = ["tab1", "tab2"];
		defaultProps.active = "tab1";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tabs {...defaultProps} />
			</ThemeProvider>,
		);
		const tabs = screen.getAllByTestId("tab");
		fireEvent.click(tabs[1]);
		expect(setSelectedTabAction).toBeCalled();
	});

	it("should render tabs row with icons if icons available", async () => {
		defaultProps.tabs = undefined;
		defaultProps.icons = [
			{ name: "edit", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];

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

		const iconTabsRow = screen.getByTestId("icons-tabs-row");
		expect(iconTabsRow).toBeTruthy();
	});

	it("should render tabs row with icons if icons available", async () => {
		defaultProps.tabs = undefined;
		defaultProps.icons = [
			{ name: "edit", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];

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

		const iconTabsRow = screen.getByTestId("icons-tabs-row");
		const tabs = screen.getAllByTestId("icon-tab");
		expect(iconTabsRow).toBeTruthy();
		expect(tabs.length).toEqual(2);
	});

	it("should render tooltip with icon's text", async () => {
		defaultProps.tabs = undefined;
		defaultProps.icons = [
			{ name: "edit", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];

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

		const tooltips = screen.getAllByTestId("tooltip-component");
		expect(tooltips[0]).toBeTruthy();
		expect(tooltips[0].textContent).toBe("Edit mode");
		expect(tooltips[1]).toBeTruthy();
		expect(tooltips[1].textContent).toBe("Preview mode");
	});

	it("should not display icon if doesn't exist", async () => {
		defaultProps.icons = [
			{ name: "failed-icon", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];
		defaultProps.active = "edit";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tabs {...defaultProps} />
			</ThemeProvider>,
		);
		const tooltips = screen.getAllByTestId("tooltip-component");
		expect(tooltips[0]).toBeTruthy();
		expect(tooltips[1]).toBeTruthy();
		const tooltipIcons = screen.getAllByTestId("icon-component-view");
		expect(tooltipIcons.length).toEqual(1);
	});
});

describe("Tabs component events", () => {
	it("should set tab as active on click", async () => {
		defaultProps.tabs = ["tab1", "tab2"];
		defaultProps.active = "tab1";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tabs {...defaultProps} />
			</ThemeProvider>,
		);
		const tabs = screen.getAllByTestId("tab");
		fireEvent.click(tabs[1]);
		expect(setSelectedTabAction).toBeCalled();
		expect(tabs[0]).toHaveStyleRule("cursor", "initial");
		expect(tabs[1]).toHaveStyleRule("cursor", "pointer");
	});

	it("should call set selected tab action on click icon tab", async () => {
		defaultProps.tabs = undefined;
		defaultProps.icons = [
			{ name: "edit", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];
		defaultProps.active = "edit";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tabs {...defaultProps} />
			</ThemeProvider>,
		);
		const tabs = screen.getAllByTestId("icon-tab");
		fireEvent.click(tabs[1]);
		expect(setSelectedTabAction).toBeCalled();
	});

	it("should set icon tab as active on click", async () => {
		defaultProps.icons = [
			{ name: "edit", text: "Edit mode" },
			{ name: "view", text: "Preview mode" },
		];
		defaultProps.active = "edit";
		const setSelectedTabAction = jest.fn();
		defaultProps.setSelectedTab = setSelectedTabAction;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Tabs {...defaultProps} />
			</ThemeProvider>,
		);
		const tabs = screen.getAllByTestId("icon-tab");
		fireEvent.click(tabs[1]);
		expect(setSelectedTabAction).toBeCalled();
		expect(tabs[0]).toHaveStyleRule("cursor", "initial");
		expect(tabs[1]).toHaveStyleRule("cursor", "pointer");
	});
});
