import { Router } from "react-router-dom";

import "@testing-library/jest-dom";

import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";

import userEvent from "@testing-library/user-event";
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import { createMemoryHistory } from "history";
import type { Middleware } from "redux";
import configureStore from "redux-mock-store";
import thunk from "redux-thunk";
import { ThemeProvider } from "styled-components";

import { act, cleanup, render, screen, waitFor } from "./../../../../../../config/jest/test-utils";
import { defaultStore } from "./../../../../../__mocks__/store/GenericStore";
import {
	appStoreMock,
	sitesStoreGlobalMock,
	usersSiteStoreMock,
	usersStoreMock,
} from "../../../../../__mocks__/store/UserList";
import UserItem, { type IUserItemProps } from "./../../../../../modules/Users/UserList/UserItem";

const middlewares: Middleware[] = [thunk];
const mockStore = configureStore(middlewares);

const user = userEvent.setup();

const history = createMemoryHistory();

let mockedAxios: MockAdapter;

const onChangeMock = jest.fn();
const onClickMock = jest.fn();
const deleteUserMock = jest.fn();
const resendInvitationMock = jest.fn();
const getUsersMock = jest.fn();
const removeUserFromSiteMock = jest.fn();
const toggleDeleteToastMock = jest.fn();
const defaultProps: IUserItemProps = {
	user: {
		id: 171,
		username: "pruebauser",
		name: "Prueba Prueba",
		email: "prueba@secuoyas.com",
		image: {
			id: 811,
			name: "Novak-Djokovic1-1536x961.jpg",
			title: "",
			description: "",
			alt: "",
			tags: [],
			url: "http://images.dev.griddo.io/novak-djokovic1-1536x961",
			thumb: "http://images.dev.griddo.io/w/215/h/161/novak-djokovic1-1536x961",
			publicId: "thesaurus-dev/Novak-Djokovic1-1536x961_4b074dc5-d5b4-4b5f-a220-9b7e7a3f3310",
			damId: "novak-djokovic1-1536x961",
			published: new Date("2022-01-20T16:24:25Z"),
			size: 160626,
			width: 1536,
			height: 961,
			orientation: "L",
			site: null,
			folderId: null,
		},
		failed: 0,
		timezone: "Europe/Madrid",
		enabled: true,
		status: "active",
		roles: [
			{ siteId: "global", roles: [1] },
			{ siteId: 2, roles: [1] },
			{ siteId: 81, roles: [1] },
		],
		isSuperAdmin: false,
	},
	sites: [
		{
			id: 1,
			name: "Site 1",
			theme: "default-theme",
			author: "prueba",
			pages: [],
			updated: true,
			home: "//cx.dev.griddo.io/pre-griddo/componentfolder",
			isPublished: false,
			bigAvatar: "http://images.dev.griddo.io/griddo-site-thumbnail-ec2ab0ba-9424-4424-8f60-222ec746902d_10",
			favicon: "https://images.dev.griddo.io/by-themascot-1920_2",
			published: "2021-11-03T10:42:32.000Z",
			smallAvatar: "http://images.dev.griddo.io/griddo-site-thumbnail-ec2ab0ba-9424-4424-8f60-222ec746902d_9",
			timezone: "Pacific/Pago_Pago",
			lastAccess: "2022-09-05T07:34:19.000Z",
			defaultLanguage: 2,
			thumbnail: "sdfasfdasf",
			path: "asdfasdf",
			domain: 1,
			navigationModules: null,
		},
		{
			id: 2,
			name: "Site 2",
			theme: "default-theme",
			author: "prueba",
			pages: [],
			updated: true,
			home: "//cx.dev.griddo.io/pre-griddo/componentfolder",
			isPublished: false,
			bigAvatar: "http://images.dev.griddo.io/griddo-site-thumbnail-ec2ab0ba-9424-4424-8f60-222ec746902d_10",
			favicon: "https://images.dev.griddo.io/by-themascot-1920_2",
			published: "2021-11-03T10:42:32.000Z",
			smallAvatar: "http://images.dev.griddo.io/griddo-site-thumbnail-ec2ab0ba-9424-4424-8f60-222ec746902d_9",
			timezone: "Pacific/Pago_Pago",
			lastAccess: "2022-09-05T07:34:19.000Z",
			navigationModules: null,
			defaultLanguage: 2,
			thumbnail: "sdfasfdasf",
			path: "asdfasdf",
			domain: 1,
		},
	],
	roles: [
		{
			id: 1,
			name: "Administrator",
			hex: "#C7ECF8",
			description:
				"You can manage all of your site's settings, users and roles. You can create and publish all pages of your site.",
			permissions: { totalPermissions: "78/78", sitePermissions: [], globalPermissions: [] },
			active: true,
			users: [],
		},
		{
			id: 2,
			name: "Constructor",
			hex: "#B5FBFF",
			description:
				"You can edit your website, add pages, modules, modify URLs, menus, colours and themes, html tags. You don't manage users, or manage the site configuration.",
			permissions: { totalPermissions: "49/78", sitePermissions: [], globalPermissions: [] },
			active: false,
			users: [],
		},
		{
			id: 3,
			name: "Editor",
			hex: "#E2EE9F",
			description: "You have permission to view, add and edit site content, such as pages and blocks.",
			permissions: { totalPermissions: "21/78", sitePermissions: [], globalPermissions: [] },
			active: true,
			users: [],
		},
		{
			id: 4,
			name: "SEO Validator",
			hex: "#FFD7C0",
			description: "You can manage SEO tags.",
			permissions: { totalPermissions: "18/78", sitePermissions: [], globalPermissions: [] },
			active: false,
			users: [],
		},
		{
			id: 5,
			name: "Viewer",
			hex: "#BCCBFF",
			description: "You can view the content, but you cannot edit it.",
			permissions: { totalPermissions: "3/78", sitePermissions: [], globalPermissions: [] },
			active: true,
			users: [],
		},
	],
	isSelected: false,
	hoverCheck: false,
	onChange: onChangeMock,
	onClick: onClickMock,
	deleteUser: deleteUserMock,
	resendInvitation: resendInvitationMock,
	toggleDeleteToast: toggleDeleteToastMock,
	getUsers: getUsersMock,
	removeUserFromSite: removeUserFromSiteMock,
};

beforeAll(() => {
	mockedAxios = new MockAdapter(axios);
});

afterEach(() => {
	cleanup();
	jest.clearAllMocks();
});

describe("UserItem module rendering", () => {
	it("should render the componet", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		expect(screen.getByTestId("user-item")).toBeTruthy();
		expect(screen.getByLabelText("Prueba Prueba")).toBeTruthy();
		expect(screen.getByText("Prueba Prueba")).toBeInTheDocument();
		//expect(screen.getByText("prueba@secuoyas.com")).toBeInTheDocument();
		expect(screen.getByText("@pruebauser")).toBeInTheDocument();
		expect(screen.getByText("Administrator")).toBeInTheDocument();
		expect(screen.getByTestId("sites-cell")).toBeTruthy();
		expect(screen.getByTestId("status-cell")).toBeTruthy();
		expect(screen.queryByTestId("modal-delete-content")).toBeFalsy();
	});

	it("should render the componet in site", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} isSiteView={true} siteId={2} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		expect(screen.getByTestId("user-item")).toBeTruthy();
		expect(screen.getByLabelText("Prueba Prueba")).toBeTruthy();
		expect(screen.getByText("Prueba Prueba")).toBeInTheDocument();
		//expect(screen.getByText("prueba@secuoyas.com")).toBeInTheDocument();
		expect(screen.getByText("@pruebauser")).toBeInTheDocument();
		expect(screen.getByText("Administrator")).toBeInTheDocument();
		expect(screen.queryByTestId("sites-cell")).toBeFalsy();
		expect(screen.queryByTestId("status-cell")).toBeFalsy();
		expect(screen.queryByTestId("modal-delete-content")).toBeFalsy();
	});
});

describe("UserItem events", () => {
	it("should call onchange on checkbox click", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		const checkbox = screen.getByLabelText("Prueba Prueba");
		expect(checkbox).toBeTruthy();
		await user.click(checkbox);

		expect(onChangeMock).toBeCalledWith({ isChecked: true, value: 171 });
	});

	it("should call onclick on user click", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		const userCell = screen.getByTestId("user-cell");
		expect(userCell).toBeTruthy();
		await user.click(userCell);

		expect(onClickMock).toBeCalledWith(171);
	});

	it("should delete user", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
			users: usersStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });
		mockedAxios.onDelete("undefined/user/171").reply(200, {});
		mockedAxios.onGet(`undefined/users?order=dateCreated`).reply(200, []);

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		const iconAction = screen.getByTestId("icon-action-component");
		await user.click(iconAction);

		const deleteItem = screen.getByText("delete");
		await user.click(deleteItem);

		expect(screen.getByTestId("modal-delete-content")).toBeTruthy();

		const deleteButton = screen.getByText("Delete");
		await user.click(deleteButton);

		await waitFor(() => expect(screen.queryByTestId("modal-delete-content")).toBeFalsy());

		expect(store.getActions()).toContainEqual({
			payload: { users: [] },
			type: "users/SET_USERS",
		});
	});

	it("should remove user from site", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
			users: usersSiteStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });
		mockedAxios.onDelete("undefined/user/171/site/2").reply(200, {});
		mockedAxios.onGet(`undefined/users`).reply(200, []);

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} isSiteView={true} siteId={2} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		const iconAction = screen.getByTestId("icon-action-component");
		await user.click(iconAction);

		const removeItem = screen.getByText("remove");
		await user.click(removeItem);

		expect(screen.getByTestId("modal-delete-content")).toBeTruthy();

		const removeButton = screen.getByText("Remove");
		await user.click(removeButton);
		await waitFor(() => expect(screen.queryByTestId("modal-delete-content")).toBeFalsy());

		/*expect(store.getActions()).toContainEqual({
      payload: { users: [] },
      type: "users/SET_USERS",
    });*/
	});

	it("should resend invitation", async () => {
		const initialStore = {
			sites: sitesStoreGlobalMock,
			app: appStoreMock,
		};

		const store = mockStore({ ...defaultStore, ...initialStore });
		mockedAxios.onPut("undefined/user/171/resend").reply(200, {});

		defaultProps.user.status = "invited";

		const Component = (
			<Router history={history}>
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<UserItem {...defaultProps} />
				</ThemeProvider>
			</Router>
		);

		await act(async () => {
			render(Component, { store });
		});

		expect(screen.queryByTestId("toast-wrapper")).toBeFalsy();

		const iconAction = screen.getByTestId("icon-action-component");
		await user.click(iconAction);

		const resendItem = screen.getByText("Resend invitation");
		await user.click(resendItem);

		await waitFor(() => expect(screen.getByTestId("toast-wrapper")).toBeTruthy());
	});
});
