import 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 KeywordsPreviewModal from "@ax/components/KeywordsPreviewModal";
import * as keywordsUtils from "@ax/components/KeywordsPreviewModal/utils";
import globalTheme from "@ax/themes/theme.json";

jest.mock("@ax/components/KeywordsPreviewModal/utils", () => ({
	...jest.requireActual("@ax/components/KeywordsPreviewModal/utils"),
	countKeywords: jest.fn().mockReturnValue({}),
}));

afterEach(cleanup);

const browserRef = { current: document.createElement("div") } as React.RefObject<HTMLDivElement>;

const defaultProps = {
	isOpen: false,
	browserRef: { current: null } as React.RefObject<HTMLDivElement>,
	toggleModal: jest.fn(),
	keywords: ["seo", "react"],
	keywordsFilter: [] as string[],
	setKeywordsFilter: jest.fn(),
	addKeywords: jest.fn(),
	deleteKeyword: jest.fn(),
};

const renderComponent = (props = defaultProps) =>
	render(
		<ThemeProvider theme={parseTheme(globalTheme)}>
			<KeywordsPreviewModal {...props} />
		</ThemeProvider>,
	);

describe("KeywordsPreviewModal component rendering", () => {
	it("should not render the keywords content when closed", () => {
		renderComponent();

		expect(screen.queryByText("Add new keyword")).toBeNull();
		expect(screen.queryByText("Show keyword:")).toBeNull();
	});

	it("should render the Add new keyword button when open", () => {
		renderComponent({ ...defaultProps, isOpen: true });

		expect(screen.getByText("Add new keyword")).toBeTruthy();
	});

	it("should render keyword items when open with keywords", () => {
		(keywordsUtils.countKeywords as jest.Mock).mockReturnValueOnce({ seo: 3, react: 1 });

		renderComponent({ ...defaultProps, isOpen: true, browserRef });

		expect(screen.getByText("seo")).toBeTruthy();
		expect(screen.getByText("react")).toBeTruthy();
	});

	it("should render keyword count for each keyword item", () => {
		(keywordsUtils.countKeywords as jest.Mock).mockReturnValueOnce({ seo: 3 });

		renderComponent({ ...defaultProps, isOpen: true, browserRef });

		expect(screen.getByText("3 used")).toBeTruthy();
	});

	it("should render the filter section when keywordsFilter is set", () => {
		renderComponent({ ...defaultProps, isOpen: true, keywordsFilter: ["seo"] });

		expect(screen.getByText("Show keyword:")).toBeTruthy();
		const seoElements = screen.getAllByText("seo");
		expect(seoElements.length).toBeGreaterThan(0);
	});

	it("should not render the filter section when keywordsFilter is empty", () => {
		renderComponent({ ...defaultProps, isOpen: true });

		expect(screen.queryByText("Show keyword:")).toBeNull();
	});
});

describe("KeywordsPreviewModal component events", () => {
	it("should call toggleModal when close button is clicked", () => {
		const toggleModalMock = jest.fn();

		renderComponent({ ...defaultProps, isOpen: true, toggleModal: toggleModalMock });

		const closeButtons = screen.getAllByTestId("icon-action-component");
		fireEvent.click(closeButtons[0]);
		expect(toggleModalMock).toBeCalled();
	});

	it("should call setKeywordsFilter with empty array when filter tag is deleted", () => {
		const setKeywordsFilterMock = jest.fn();

		renderComponent({
			...defaultProps,
			isOpen: true,
			keywordsFilter: ["seo"],
			setKeywordsFilter: setKeywordsFilterMock,
		});

		const deleteIconWrapper = screen.getByTestId("delete-icon-wrapper");
		fireEvent.click(deleteIconWrapper);
		expect(setKeywordsFilterMock).toBeCalledWith([]);
	});

	it("should call setKeywordsFilter with the clicked keyword when a keyword item is clicked", () => {
		const setKeywordsFilterMock = jest.fn();
		(keywordsUtils.countKeywords as jest.Mock).mockReturnValueOnce({ seo: 3 });

		renderComponent({ ...defaultProps, isOpen: true, browserRef, setKeywordsFilter: setKeywordsFilterMock });

		const keywordItems = screen.getAllByRole("button");
		const seoItem = keywordItems.find((el) => el.textContent?.includes("seo") && el.getAttribute("tabindex") === "0");
		expect(seoItem).toBeTruthy();
		fireEvent.click(seoItem!);
		expect(setKeywordsFilterMock).toBeCalledWith(["seo"]);
	});
});
