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

afterEach(cleanup);
const defaultProps = mock<IComponentContainerProps>();

describe("ComponentContainer component rendering", () => {
	afterEach(() => {
		jest.resetAllMocks();
	});
	test("should render the ComponentContainer", () => {
		defaultProps.text = "texto";
		defaultProps.editorID = 1;
		defaultProps.whiteList = ["BasicContent", "CardCollection"];
		defaultProps.arrayLength = 10;
		defaultProps.theme = "default";
		defaultProps.isArray = true;
		defaultProps.disabled = false;
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ComponentContainer {...defaultProps} />
			</ThemeProvider>,
		);

		expect(screen.getAllByTestId("component-container")).toBeTruthy();
	});
	test("should render the EmptyContainer with whitelist value", () => {
		// biome-ignore lint/suspicious/noTsIgnore: TODO: fix this
		// @ts-ignore
		defaultProps.text = undefined;
		// biome-ignore lint/suspicious/noTsIgnore: TODO: fix this
		// @ts-ignore
		defaultProps.editorID = undefined;
		defaultProps.whiteList = ["BasicContent", "CardCollection"];
		defaultProps.isArray = false;
		defaultProps.arrayLength = 10;
		defaultProps.theme = "default";
		defaultProps.value = {};
		defaultProps.actionReplace = jest.fn();
		defaultProps.actions = {
			addComponentAction: jest.fn(),
			deleteModuleAction: jest.fn(),
			duplicateModuleAction: jest.fn(),
			copyModuleAction: jest.fn(),
			replaceModuleAction: jest.fn(),
		};
		defaultProps.canDuplicate = true;
		defaultProps.canReplace = true;
		defaultProps.objKey = "component";
		defaultProps.selectedContent = {
			component: "Section",
			name: "Main Content",
			modules: [
				{
					component: "BasicContent",
					title: {
						content: "Title",
						tag: "h1",
					},
					anchorID: null,
					verticalSpacing: "medium",
					layout: "L001",
					theme: "default",
					moduleOrder: null,
					subtitle:
						"Lorem ipsum dolor sit amet, consectetur adipiscsdcdscing elit. Morbi dignissim ut nibh eget porttitor. Nunc eleifend mollis arcu.sdcsdc",
					content:
						"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim ut nibh eget porttitor. Nunc eleifend mollis arcu. Lorem ipsum d</p>",
					primaryLink: {
						component: "Link",
						text: "Link 1",
						style: "primary",
						url: {
							url: "",
							linkTo: null,
							newTab: false,
							noFollow: false,
							size: null,
							icon: null,
							linkContainer: null,
						},
						editorID: 5,
						parentEditorID: 4,
					},
					secondaryLink: {
						component: "Link",
						editorID: 6,
						parentEditorID: 4,
					},
					additionalContent: {
						image: {
							component: "LinkableImage",
							editorID: 7,
							parentEditorID: 4,
						},
						video: {
							component: "Video",
							editorID: 8,
							parentEditorID: 4,
						},
					},
					editorID: 4,
					parentEditorID: 3,
				},
			],
			sectionPosition: 2,
			editorID: 3,
			parentEditorID: 1,
			key: "mainContent",
		};
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ComponentContainer {...defaultProps} />
			</ThemeProvider>,
		);
		expect(screen.getAllByTestId("field-multiple-options")).toBeTruthy();
	});
	test("should render the EmptyContainer with title", () => {
		defaultProps.title = "a title";
		defaultProps.whiteList = ["BasicContent", "CardCollection"];
		defaultProps.isArray = false;
		defaultProps.arrayLength = 10;
		defaultProps.theme = "default";
		defaultProps.value = {};
		defaultProps.actionReplace = jest.fn();
		defaultProps.actions = {
			addComponentAction: jest.fn(),
			deleteModuleAction: jest.fn(),
			duplicateModuleAction: jest.fn(),
			copyModuleAction: jest.fn(),
			replaceModuleAction: jest.fn(),
		};
		defaultProps.canDuplicate = true;
		defaultProps.canReplace = true;
		defaultProps.objKey = "component";
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ComponentContainer {...defaultProps} />
			</ThemeProvider>,
		);
		expect(screen.getAllByTestId("field-multiple-options")).toBeTruthy();
	});
	test("should render the icon with the container text", () => {
		defaultProps.text = "texto a mostrar";
		defaultProps.editorID = 1;
		defaultProps.whiteList = ["BasicContent", "CardCollection"];
		defaultProps.isArray = false;
		defaultProps.disabled = false;
		defaultProps.arrayLength = 10;
		defaultProps.theme = "default";
		defaultProps.value = {
			component: "Link",
			text: "Link 1",
			style: "primary",
			url: {
				url: "",
				linkTo: null,
				newTab: false,
				noFollow: false,
				size: null,
				icon: null,
				linkContainer: null,
			},
			editorID: 5,
			parentEditorID: 4,
		};
		defaultProps.actions = {
			addComponentAction: jest.fn(),
			deleteModuleAction: jest.fn(),
			duplicateModuleAction: jest.fn(),
			copyModuleAction: jest.fn(),
			replaceModuleAction: jest.fn(),
		};
		defaultProps.parentKey = "title";
		defaultProps.objKey = "content";
		defaultProps.selectedContent = {
			component: "BasicContent",
			title: {
				content: "Title",
				tag: "h1",
			},
			anchorID: null,
			verticalSpacing: "medium",
			layout: "L001",
			theme: "default",
			moduleOrder: null,
			subtitle:
				"Lorem ipsum dolor sit amet, consectetur adipiscsdcdscing elit. Morbi dignissim ut nibh eget porttitor. Nunc eleifend mollis arcu.sdcsdc",
			content:
				"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim ut nibh eget porttitor. Nunc eleifend mollis arcu. Lorem ipsum d</p>",
			primaryLink: {
				component: "Link",
				text: "Link 1",
				style: "primary",
				url: {
					url: "",
					linkTo: null,
					newTab: false,
					noFollow: false,
					size: null,
					icon: null,
					linkContainer: null,
				},
				editorID: 5,
				parentEditorID: 4,
			},
			secondaryLink: {
				component: "Link",
				editorID: 6,
				parentEditorID: 4,
			},
			additionalContent: {
				image: {
					component: "LinkableImage",
					editorID: 7,
					parentEditorID: 4,
				},
				video: {
					component: "Video",
					editorID: 8,
					parentEditorID: 4,
				},
			},
			editorID: 4,
			parentEditorID: 3,
		};
		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ComponentContainer {...defaultProps} />
			</ThemeProvider>,
		);
		expect(screen.getByTestId("icon-wrapper")).toBeTruthy();
		expect(screen.findByText("texto a mostrar")).toBeTruthy();
	});

	test("should render the title", () => {
		defaultProps.text = "texto a mostrar";
		defaultProps.moduleTitle = "module title";
		defaultProps.editorID = 1;
		defaultProps.whiteList = [];
		defaultProps.isArray = false;
		defaultProps.disabled = false;
		defaultProps.arrayLength = 10;
		defaultProps.theme = "default";
		defaultProps.value = {
			component: "Link",
			text: "Link 1",
			style: "primary",
			url: {
				url: "",
				linkTo: null,
				newTab: false,
				noFollow: false,
				size: null,
				icon: null,
				linkContainer: null,
			},
			editorID: 5,
			parentEditorID: 4,
		};

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<ComponentContainer {...defaultProps} />
			</ThemeProvider>,
		);
		expect(screen.findByText("module title")).toBeTruthy();
	});

	test("should render the SideModal when click EmptyContainer", () => {
		defaultProps.title = "a title";
		defaultProps.whiteList = ["LinkImage", "Video"];
		defaultProps.isArray = false;
		defaultProps.arrayLength = 2;
		defaultProps.theme = "griddo-alt-theme";
		defaultProps.editorID = 1;
		defaultProps.value = {
			image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
			video: { component: "Video", editorID: 3, parentEditorID: 1 },
		};
		defaultProps.actionReplace = jest.fn();
		defaultProps.actions = {
			addComponentAction: jest.fn(),
			deleteModuleAction: jest.fn(),
			duplicateModuleAction: jest.fn(),
			copyModuleAction: jest.fn(),
			replaceModuleAction: jest.fn(),
		};
		defaultProps.canDuplicate = true;
		defaultProps.canReplace = true;
		defaultProps.objKey = "component";

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

		const multipleOptionsField = screen.getByTestId("field-multiple-options");
		expect(multipleOptionsField).toBeTruthy();
		fireEvent.click(multipleOptionsField);
		const sideModal = screen.getByTestId("side-modal");
		expect(sideModal).toBeTruthy();
	});

	test("should render component options on SideModal", () => {
		defaultProps.title = "a title";
		defaultProps.whiteList = ["LinkImage", "Video"];
		defaultProps.isArray = false;
		defaultProps.arrayLength = 2;
		defaultProps.theme = "griddo-alt-theme";
		defaultProps.editorID = 1;
		defaultProps.value = {
			image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
			video: { component: "Video", editorID: 3, parentEditorID: 1 },
		};
		defaultProps.actionReplace = jest.fn();
		defaultProps.actions = {
			addComponentAction: jest.fn(),
			deleteModuleAction: jest.fn(),
			duplicateModuleAction: jest.fn(),
			copyModuleAction: jest.fn(),
			replaceModuleAction: jest.fn(),
		};
		defaultProps.canDuplicate = true;
		defaultProps.canReplace = true;
		defaultProps.objKey = "component";

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

		const multipleOptionsField = screen.getByTestId("field-multiple-options");
		expect(multipleOptionsField).toBeTruthy();
		fireEvent.click(multipleOptionsField);
		const sideModal = screen.getByTestId("side-modal");
		expect(sideModal).toBeTruthy();
		const options = screen.getAllByTestId("side-modal-option");
		expect(options.length).toEqual(2);
	});
});

test("should render the FloatingMenu with options when click Component Container", async () => {
	defaultProps.title = "a title";
	defaultProps.whiteList = ["LinkImage", "Video"];
	defaultProps.isArray = false;
	defaultProps.arrayLength = 2;
	defaultProps.theme = "griddo-alt-theme";
	defaultProps.editorID = 1;
	defaultProps.value = {
		image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
		video: {
			component: "Video",
			editorID: 3,
			parentEditorID: 1,
			thumbnail: { component: "Image", editorID: 4, parentEditorID: 3 },
			url: "",
		},
	};
	defaultProps.actionReplace = jest.fn();
	defaultProps.actions = {
		addComponentAction: jest.fn(),
		deleteModuleAction: jest.fn(),
		duplicateModuleAction: jest.fn(),
		copyModuleAction: jest.fn(),
		replaceModuleAction: jest.fn(),
	};
	defaultProps.canDuplicate = true;
	defaultProps.canReplace = true;
	defaultProps.objKey = "component";

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

	const component = screen.getByTestId("component-container");
	fireEvent.mouseOver(component);
	const floatingMenu = screen.getByTestId("floating-menu-button");
	expect(floatingMenu).toBeTruthy();
	fireEvent.click(floatingMenu);
	const actionMenu = screen.getByTestId("action-menu-item");
	expect(actionMenu).toBeTruthy();
	const actionMenuItems = screen.getAllByTestId("action-menu-item");
	expect(actionMenuItems.length).toEqual(1);
});

test("should render the SideModal with options when click the replace action", async () => {
	defaultProps.title = "a title";
	defaultProps.whiteList = ["LinkImage", "Video"];
	defaultProps.isArray = false;
	defaultProps.arrayLength = 2;
	defaultProps.theme = "griddo-alt-theme";
	defaultProps.editorID = 1;
	defaultProps.value = {
		image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
		video: {
			component: "Video",
			editorID: 3,
			parentEditorID: 1,
			thumbnail: { component: "Image", editorID: 4, parentEditorID: 3 },
			url: "",
		},
	};
	defaultProps.actionReplace = jest.fn();
	defaultProps.actions = {
		addComponentAction: jest.fn(),
		deleteModuleAction: jest.fn(),
		duplicateModuleAction: jest.fn(),
		copyModuleAction: jest.fn(),
		replaceModuleAction: jest.fn(),
	};
	defaultProps.canDuplicate = true;
	defaultProps.canReplace = true;
	defaultProps.objKey = "component";

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

	const component = screen.getByTestId("component-container");
	fireEvent.mouseOver(component);

	const floatingMenu = screen.getByTestId("floating-menu-button");
	expect(floatingMenu).toBeTruthy();

	fireEvent.click(floatingMenu);
	const actionMenu = screen.getByTestId("action-menu-item");
	expect(actionMenu).toBeTruthy();

	const actionMenuItem = screen.getByTestId("action-menu-item");
	fireEvent.click(actionMenuItem);
	const sideModal = screen.getByTestId("side-modal");
	expect(sideModal).toBeTruthy();

	const options = screen.getAllByTestId("side-modal-option");
	expect(options.length).toEqual(2);
});

test("should not render the drag handle if arrays length is lower than two", async () => {
	defaultProps.title = "a title";
	defaultProps.whiteList = ["LinkImage", "Video"];
	defaultProps.isArray = false;
	defaultProps.arrayLength = 1;
	defaultProps.theme = "griddo-alt-theme";
	defaultProps.editorID = 1;
	defaultProps.value = {
		image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
		video: {
			component: "Video",
			editorID: 3,
			parentEditorID: 1,
			thumbnail: { component: "Image", editorID: 4, parentEditorID: 3 },
			url: "",
		},
	};
	defaultProps.actionReplace = jest.fn();
	defaultProps.actions = {
		addComponentAction: jest.fn(),
		deleteModuleAction: jest.fn(),
		duplicateModuleAction: jest.fn(),
		copyModuleAction: jest.fn(),
		replaceModuleAction: jest.fn(),
	};
	defaultProps.canDuplicate = true;
	defaultProps.canReplace = true;
	defaultProps.objKey = "component";

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

	const handleWrapper = screen.queryByTestId("handle-wrapper");
	expect(handleWrapper).toBeFalsy();
});

test("should render the drag handle if arrays length is greater than two", async () => {
	defaultProps.title = "a title";
	defaultProps.whiteList = ["LinkImage", "Video"];
	defaultProps.isArray = true;
	defaultProps.arrayLength = 3;
	defaultProps.theme = "griddo-alt-theme";
	defaultProps.editorID = 1;
	defaultProps.value = {
		image: { component: "LinkableImage", editorID: 2, parentEditorID: 1 },
		video: {
			component: "Video",
			editorID: 3,
			parentEditorID: 1,
			thumbnail: { component: "Image", editorID: 4, parentEditorID: 3 },
			url: "",
		},
	};
	defaultProps.actionReplace = jest.fn();
	defaultProps.actions = {
		addComponentAction: jest.fn(),
		deleteModuleAction: jest.fn(),
		duplicateModuleAction: jest.fn(),
		copyModuleAction: jest.fn(),
		replaceModuleAction: jest.fn(),
	};
	defaultProps.canDuplicate = true;
	defaultProps.canReplace = true;
	defaultProps.objKey = "component";

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

	const handleWrapper = screen.getByTestId("handle-wrapper");
	expect(handleWrapper).toBeTruthy();
});
