import "jest-styled-components";

import Pagination, { type IPaginationProps } from "@ax/components/Pagination";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";

import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { mock } from "jest-mock-extended";
import { ThemeProvider } from "styled-components";

afterEach(cleanup);

const defaultProps = mock<IPaginationProps>();

describe("Pagination component rendering", () => {
	it("should render pagination component", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;

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

		const paginationWrapper = screen.getByTestId("pagination-wrapper");
		expect(paginationWrapper).toBeTruthy();
	});

	it("should render pagination label when size equals 'S'", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

		const paginationLabel = screen.getByTestId("pagination-label");
		expect(paginationLabel.textContent).toEqual("Page 1 of 2");
	});

	it("should render pagination text input when size is undefined", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = undefined;

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

		const paginationTextInput = screen.getByTestId("pagination-text-input");
		expect(paginationTextInput).toBeTruthy();
	});

	it("should render arrow left disabled when it's first page", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

		const iconActionComponents = screen.getAllByTestId("icon-action-component");
		expect(iconActionComponents.length).toEqual(2);

		expect(iconActionComponents[0]).toHaveStyleRule("pointer-events", "none");
	});

	it("should render arrow right disabled when it's last page", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 2;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

		const iconActionComponents = screen.getAllByTestId("icon-action-component");

		expect(iconActionComponents[0]).toHaveStyleRule("pointer-events", "auto");
		expect(iconActionComponents[1]).toHaveStyleRule("pointer-events", "none");
	});
});

describe("Pagination component events", () => {
	it("should call setPage when click next page button", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

		const iconActionComponents = screen.getAllByTestId("icon-action-component");
		fireEvent.click(iconActionComponents[1]);
		expect(setPageMock).toBeCalled();
	});

	it("should call setPage when click next page button", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

		const iconActionComponents = screen.getAllByTestId("icon-action-component");
		fireEvent.click(iconActionComponents[1]);
		expect(setPageMock).toBeCalled();
	});

	it("should call setPage when click prev page button", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 2;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = "S";

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

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

	it("should call setPage when change input value and blur", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = undefined;

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

		const paginationTextInput = screen.getByTestId("pagination-text-input");
		fireEvent.change(paginationTextInput, { target: { value: 2 } });
		fireEvent.blur(paginationTextInput);
		expect(setPageMock).toBeCalled();
	});

	it("should call setPage with 1 when change input value is not a number", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = undefined;

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

		const paginationTextInput = screen.getByTestId("pagination-text-input");
		fireEvent.change(paginationTextInput, { target: { value: "A" } });
		fireEvent.blur(paginationTextInput);
		expect(setPageMock).toBeCalledWith(1);
	});

	it("shouldn't call setPage when current page is lower than or equal to 1", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 1;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = undefined;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Pagination {...defaultProps} />
			</ThemeProvider>,
		);
		const iconActionComponents = screen.getAllByTestId("icon-action-component");
		fireEvent.click(iconActionComponents[0]);
		expect(setPageMock).not.toHaveBeenCalled();
	});

	it("shouldn't call setPage when current page is greater than or equal to last page", () => {
		const setPageMock = jest.fn();
		defaultProps.currPage = 2;
		defaultProps.itemsPerPage = 10;
		defaultProps.setPage = setPageMock;
		defaultProps.totalItems = 14;
		defaultProps.size = undefined;

		render(
			<ThemeProvider theme={parseTheme(globalTheme)}>
				<Pagination {...defaultProps} />
			</ThemeProvider>,
		);
		const iconActionComponents = screen.getAllByTestId("icon-action-component");
		fireEvent.click(iconActionComponents[1]);
		expect(setPageMock).not.toHaveBeenCalled();
	});
});
