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 ErrorItem from "@ax/components/HeadingsPreviewModal/ErrorsBanner/ErrorItem";
import type { IHeadingError } from "@ax/components/HeadingsPreviewModal/utils";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

const mockError: IHeadingError = {
	message: "Check heading structure for SEO compliance",
	description: "Ensure headings are properly nested",
	headingIds: [1, 2, 3],
};

const defaultProps = {
	error: mockError,
	onSelectHeading: jest.fn(() => jest.fn()),
	onDelete: jest.fn(),
	onNavigateHeading: jest.fn(),
	parentIsOpen: true,
};

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

describe("ErrorItem component rendering", () => {
	it("should render the error message", () => {
		renderComponent();
		expect(screen.getByText("Check heading structure for SEO compliance")).toBeTruthy();
	});

	it("should show heading counter text", () => {
		renderComponent();
		expect(screen.getByText("3 headings")).toBeTruthy();
	});

	it("should show the open toggle button when headingIds are present", () => {
		renderComponent();
		const buttons = screen.getAllByRole("button");
		// toggle (index 0) + close (index 1) + prev (index 2) + next (index 3)
		expect(buttons.length).toBe(4);
	});

	it("should not show the open toggle button when headingIds is empty", () => {
		const props = {
			...defaultProps,
			error: { ...mockError, headingIds: [] },
		};
		renderComponent(props);
		const buttons = screen.getAllByRole("button");
		// only close (index 0) + prev (index 1) + next (index 2) — no toggle
		expect(buttons.length).toBe(3);
	});

	it("should not render when dismissed", () => {
		renderComponent();
		expect(screen.getByText("Check heading structure for SEO compliance")).toBeTruthy();

		const buttons = screen.getAllByRole("button");
		// Close button is at index 1 (after toggle)
		fireEvent.click(buttons[1]);

		expect(screen.queryByText("Check heading structure for SEO compliance")).toBeNull();
	});
});

describe("ErrorItem component events", () => {
	it("should call onSelectHeading when the open button is clicked", () => {
		const onSelectHeadingMock = jest.fn(() => jest.fn());
		renderComponent({ ...defaultProps, onSelectHeading: onSelectHeadingMock });

		const buttons = screen.getAllByRole("button");
		// Toggle open is at index 0
		fireEvent.click(buttons[0]);

		expect(onSelectHeadingMock).toBeCalledWith(mockError.headingIds[0]);
	});

	it("should update counter to '1 of 3 headings' after opening", () => {
		renderComponent();

		const buttons = screen.getAllByRole("button");
		fireEvent.click(buttons[0]);

		expect(screen.getByText("1 of 3 headings")).toBeTruthy();
	});

	it("should call onSelectHeading with first heading ID when next button is clicked", () => {
		const onSelectHeadingMock = jest.fn(() => jest.fn());
		renderComponent({ ...defaultProps, onSelectHeading: onSelectHeadingMock });

		const buttons = screen.getAllByRole("button");
		// Next button is at index 3 (toggle, close, prev, next)
		fireEvent.click(buttons[3]);

		expect(onSelectHeadingMock).toBeCalledWith(mockError.headingIds[0]);
	});

	it("should update counter to '2 of 3 headings' after two next clicks", () => {
		renderComponent();

		const buttons = screen.getAllByRole("button");
		fireEvent.click(buttons[3]);
		fireEvent.click(buttons[3]);

		expect(screen.getByText("2 of 3 headings")).toBeTruthy();
	});

	it("should call onSelectHeading with previous heading ID when prev button is clicked", () => {
		const onSelectHeadingMock = jest.fn(() => jest.fn());
		renderComponent({ ...defaultProps, onSelectHeading: onSelectHeadingMock });

		const buttons = screen.getAllByRole("button");
		// Advance to index 1, then go back
		fireEvent.click(buttons[3]);
		fireEvent.click(buttons[3]);

		jest.clearAllMocks();
		fireEvent.click(buttons[2]);

		expect(onSelectHeadingMock).toBeCalledWith(mockError.headingIds[0]);
	});

	it("should not navigate prev when already at the first heading", () => {
		const onSelectHeadingMock = jest.fn(() => jest.fn());
		renderComponent({ ...defaultProps, onSelectHeading: onSelectHeadingMock });

		const buttons = screen.getAllByRole("button");
		// Open sets currentIndex to 0, then try to go prev
		fireEvent.click(buttons[0]);
		jest.clearAllMocks();
		fireEvent.click(buttons[2]);

		expect(onSelectHeadingMock).not.toBeCalled();
	});

	it("should not navigate next when already at the last heading", () => {
		const onSelectHeadingMock = jest.fn(() => jest.fn());
		renderComponent({ ...defaultProps, onSelectHeading: onSelectHeadingMock });

		const buttons = screen.getAllByRole("button");
		// Click next 3 times to reach the end (headingIds has 3 items, indices 0-2)
		fireEvent.click(buttons[3]);
		fireEvent.click(buttons[3]);
		fireEvent.click(buttons[3]);
		jest.clearAllMocks();

		// Fourth click should be a no-op
		fireEvent.click(buttons[3]);
		expect(onSelectHeadingMock).not.toBeCalled();
	});
});
