import * as React from "react";
import { BrowserRouter } from "react-router-dom";

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 AppBar, { IAppBarProps } from "@ax/components/MainWrapper/AppBar";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

describe("AppBar component rendering", () => {
	it("should render the component empty with title", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const header = screen.getByTestId("appbar-header");
		expect(header).toBeTruthy();
		expect(header).not.toHaveClass("fixed");

		const title = screen.getByText("the title");
		expect(title).toBeTruthy();

		const backButton = screen.queryByTestId("back-button-wrapper");
		expect(backButton).toBeFalsy();

		const tabsWrapper = screen.queryByTestId("tabs-wrapper");
		expect(tabsWrapper).toBeFalsy();

		const searchWrapper = screen.queryByTestId("search-wrapper");
		expect(searchWrapper).toBeFalsy();

		const languageWrapper = screen.queryByTestId("language-wrapper");
		expect(languageWrapper).toBeFalsy();

		const pageStatusWrapper = screen.queryByTestId("page-status-wrapper");
		expect(pageStatusWrapper).toBeFalsy();

		const errorCenterWrapper = screen.queryByTestId("error-center-wrapper");
		expect(errorCenterWrapper).toBeFalsy();
	});

	it("should render the component with subtitle", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			subtitle: "the subtitle",
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const subtitle = screen.getByText("the subtitle");
		expect(subtitle).toBeTruthy();
	});

	it("should render the component inversed", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			inversed: true,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const header = screen.getByTestId("appbar-header");
		expect(header).toBeTruthy();
	});

	it("should render with fixed class", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			fixedAppBar: true,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const header = screen.getByTestId("appbar-header");
		expect(header).toBeTruthy();
		expect(header).toHaveClass("fixed");
	});

	it("should render without fixed class", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			fixedAppBar: false,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const header = screen.getByTestId("appbar-header");
		expect(header).toBeTruthy();
		expect(header).not.toHaveClass("fixed");
	});

	it("should render with additional class", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			additionalClass: "customClass",
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const header = screen.getByTestId("appbar-header");
		expect(header).toBeTruthy();
		expect(header).toHaveClass("customClass");
	});

	it("should render with back link", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			backLink: true,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const backButton = screen.getByTestId("back-button-wrapper");
		expect(backButton).toBeTruthy();
	});

	it("should render tabs with icons", () => {
		const tabs = {
			icons: [
				{ name: "tab1", text: "Tab 1" },
				{ name: "tab2", text: "Tab 2" },
			],
			selectedTab: "tab1",
			action: jest.fn(),
		};

		const defaultProps: IAppBarProps = {
			title: "the title",
			tabs,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const tabsWrapper = screen.getByTestId("tabs-wrapper");
		expect(tabsWrapper).toBeTruthy();
	});

	it("should render tabs", () => {
		const tabs = {
			tabSet: ["Tab 1", "Tab 2"],
			selectedTab: "Tab 1",
			action: jest.fn(),
		};

		const defaultProps: IAppBarProps = {
			title: "the title",
			tabs,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const tabsWrapper = screen.getByTestId("tabs-wrapper");
		expect(tabsWrapper).toBeTruthy();
	});

	it("should render the search field", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			searchAction: jest.fn(),
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const searchWrapper = screen.getByTestId("search-wrapper");
		expect(searchWrapper).toBeTruthy();
	});

	it("should render the language", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			language: { locale: "es_ES", id: 4 },
			availableLanguages: [
				{
					id: 1,
					locale: "en_GB",
					language: "English",
					label: "EN",
					isDefault: true,
				},
				{
					id: 2,
					locale: "es_ES",
					language: "Spanish",
					label: "ES",
					isDefault: false,
				},
			],
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const languageWrapper = screen.getByTestId("language-wrapper");
		expect(languageWrapper).toBeTruthy();
	});

	it("should render the page status", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			pageStatus: "active",
			pageStatusActions: [
				{
					icon: "icon",
					label: "Action 1",
					action: jest.fn(),
				},
				{
					icon: "icon2",
					label: "Action 2",
					action: jest.fn(),
				},
			],
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const pageStatusWrapper = screen.getByTestId("page-status-wrapper");
		expect(pageStatusWrapper).toBeTruthy();
	});

	it("should render the error center", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			isFromEditor: true,
			errors: [
				{
					type: "error",
					message: "error message 1",
					validator: {},
					editorID: null,
					component: "",
					name: "",
					key: "",
					tab: "",
					template: false,
				},
				{
					type: "error",
					message: "error message 2",
					validator: {},
					editorID: null,
					component: "",
					name: "",
					key: "",
					tab: "",
					template: false,
				},
			],
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const errorCenterWrapper = screen.getByTestId("error-center-wrapper");
		expect(errorCenterWrapper).toBeTruthy();
	});

	it("should render the right line button", () => {
		const label = "the right line button";
		const defaultProps: IAppBarProps = {
			title: "the title",
			rightLineButton: {
				label,
				action: jest.fn(),
			},
		};

		const { getByText } = render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const button = getByText(label);
		expect(button).toBeTruthy();
	});

	it("should render the right button", () => {
		const label = "the right button";
		const defaultProps: IAppBarProps = {
			title: "the title",
			rightButton: {
				label,
				action: jest.fn(),
			},
		};

		const { getByText } = render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const button = getByText(label);
		expect(button).toBeTruthy();
	});

	it("should render the action menu", () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			downArrowMenu: {
				displayed: true,
				options: [
					{
						icon: "icon",
						label: "Action 1",
						action: jest.fn(),
					},
					{
						icon: "icon2",
						label: "Action 2",
						action: jest.fn(),
					},
				],
				button: { label: "the menu button", action: jest.fn() },
			},
		};

		const { getByTestId } = render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const arrowButtonWrapper = getByTestId("down-arrow-button-wrapper");
		expect(arrowButtonWrapper).toBeTruthy();
	});
});

describe("AppBar component events", () => {
	it("should render the language menu on click", async () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			downArrowMenu: {
				displayed: true,
				options: [
					{
						icon: "icon",
						label: "Action 1",
						action: jest.fn(),
					},
					{
						icon: "icon2",
						label: "Action 2",
						action: jest.fn(),
					},
				],
				button: { label: "the menu button", action: jest.fn() },
			},
			language: { locale: "en_GB", id: 4 },
			availableLanguages: [
				{
					domain: { id: 1, slug: "/pre-griddo", url: "//cx.dev.griddo.io/pre-griddo" },
					home: "//cx.dev.griddo.io/pre-griddo/gonzalo-h",
					id: 4,
					isDefault: true,
					label: "EN",
					language: "English",
					locale: "en_GB",
					path: "/gonzalo-h",
				},
				{
					domain: { id: 1, url: "//cx.dev.griddo.io/pre-griddo", slug: "/pre-griddo" },
					home: "//cx.dev.griddo.io/pre-griddo/gonzalo-h/es",
					id: 2,
					isDefault: false,
					label: "ES",
					language: "Spanish",
					locale: "es_ES",
					path: "/gonzalo-h/es",
				},
			],
			languageActions: {
				createNewTranslation: jest.fn(),
				getSiteContent: jest.fn(),
				setLanguage: jest.fn(),
			},
		};

		const { getByTestId, getAllByTestId } = render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const languageMenuBtn = getByTestId("language-menu-btn");
		expect(languageMenuBtn).toBeTruthy();
		fireEvent.click(languageMenuBtn);
		const languageMenu = getByTestId("language-menu");
		expect(languageMenu).toBeTruthy();
		const languageMenuItem = getAllByTestId("language-menu-item");
		expect(languageMenuItem.length).toEqual(2);
		const languageLocaleLabel = getByTestId("language-locale-label");
		expect(languageLocaleLabel.textContent).toEqual("en_GB");
		expect(languageMenuItem[0].textContent).toEqual("EN - English");
		expect(languageMenuItem[1].textContent).toEqual("ES - Spanish");
	});

	it("should render the status menu on click", async () => {
		const defaultProps: IAppBarProps = {
			title: "the title",
			downArrowMenu: {
				displayed: true,
				options: [
					{
						icon: "icon",
						label: "Action 1",
						action: jest.fn(),
					},
					{
						icon: "icon2",
						label: "Action 2",
						action: jest.fn(),
					},
				],
				button: { label: "the menu button", action: jest.fn() },
			},
			pageStatus: "active",
			pageStatusActions: [
				{
					icon: "icon",
					label: "Action 1",
					action: jest.fn(),
				},
				{
					icon: "icon2",
					label: "Action 2",
					action: jest.fn(),
				},
			],
		};

		const { getByTestId, getAllByTestId } = render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<AppBar {...defaultProps} />
			</ThemeProvider>,
			{ wrapper: BrowserRouter },
		);

		const statusBtn = getByTestId("status-button");
		expect(statusBtn).toBeTruthy();
		fireEvent.click(statusBtn);
		const actionSimpleMenu = getByTestId("action-simple-menu");
		expect(actionSimpleMenu).toBeTruthy();
		const actionMenuItem = getAllByTestId("action-menu-item");
		expect(actionMenuItem.length).toEqual(2);
	});
});
