import React from "react";
import "@testing-library/jest-dom";
import configureStore from "redux-mock-store";
import { ThemeProvider } from "styled-components";
import { mock } from "jest-mock-extended";
import axios from "axios";
import thunk from "redux-thunk";
import { Router } from "react-router-dom";
import { history } from "@ax/routes";

import { render, cleanup, act, screen, fireEvent } from "../../../../../config/jest/test-utils";

import IntegrationsField, { IIntegrationsFieldProps } from "@ax/components/Fields/IntegrationsField";
import { parseTheme } from "@ax/helpers";
import globalTheme from "@ax/themes/theme.json";

afterEach(cleanup);

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

jest.mock("axios");
const mockedAxios = axios as jest.MockedFunction<typeof axios>;

const defaultProps = mock<IIntegrationsFieldProps>();
defaultProps.site = {
	id: 86,
	name: "Site 1",
	theme: "default-theme",
	author: "",
	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",
	thumbnail: "http://images.dev.griddo.io/griddo-site-thumbnail-ec2ab0ba-9424-4424-8f60-222ec746902d_7",
	timezone: "Pacific/Pago_Pago",
	lastAccess: "2022-09-05T07:34:19.000Z",
	navigationModules: null,
	defaultLanguage: 1,
	path: "",
	domain: 1,
};

const initialStore = {
	dataPacks: { activated: [] },
	pageEditor: { template: "" },
	app: {
		globalLangs: [
			{
				id: 4,
				locale: "en_GB",
				language: "English",
				label: "EN",
				isDefault: true,
			},
			{
				id: 2,
				locale: "es_ES",
				language: "Spanish",
				label: "ES",
				isDefault: false,
			},
		],
	},
	sites: {
		currentSiteInfo: { id: 86 },
	},
	integrations: {
		integrations: [
			{
				id: 22,
				name: "Customer Support",
				description: "This is the integration for Customer Support",
				site: 86,
				contentHead: "<script>console.log('Hello')</script>",
				contentBody: "",
				contentBodyPosition: "start",
				contentPresence: {
					presenceType: null,
					relatedPages: null,
				},
				active: true,
				relatedPages: [],
			},
			{
				id: 5,
				name: "Reproductor",
				description: "This is the integration for layers",
				site: 86,
				contentHead: "",
				contentBody: "<script>console.log('Hello')</script>",
				contentBodyPosition: "start",
				contentPresence: {
					presenceType: "all",
					relatedPages: null,
				},
				active: true,
				variables: [
					{
						id: 9,
						variableName: "Pointer",
						variableKey: "color",
						defaultValue: "#FFFFF",
						value: "#123456",
						multilanguage: [],
						isMultilanguage: false,
					},
				],
				relatedPages: [],
			},
			{
				id: 4,
				name: "Cupmaker",
				description: "This is the integration for Cupmaker",
				site: 86,
				contentHead: "",
				contentBody: "<script>console.log('Hello')</script>",
				contentBodyPosition: "start",
				contentPresence: {
					presenceType: "page-specific",
					relatedPages: null,
				},
				active: true,
				variables: [
					{
						id: 3,
						variableName: "Background",
						variableKey: "color",
						defaultValue: "#FFFFF",
						value: "#111222",
						multilanguage: [],
						isMultilanguage: false,
					},
					{
						id: 10,
						variableName: "ColorCup",
						variableKey: "color",
						defaultValue: "#FFFFF",
						value: "#000000",
						multilanguage: [],
						isMultilanguage: false,
					},
				],
				relatedPages: [],
			},
			{
				id: 6,
				name: "Page custom",
				description: "This is the integration page custom",
				site: 86,
				contentHead: "<script>console.log('Hello')</script>",
				contentBody: "",
				contentBodyPosition: "start",
				contentPresence: {
					presenceType: "page-custom",
					relatedPages: null,
				},
				active: true,
				relatedPages: [],
			},
		],
		totalItems: 3,
		integrationCopy: null,
	},
	users: {
		currentUser: {
			company: "",
			dateCreated: null,
			description: "",
			email: "bot@secuoyas.com",
			enabled: true,
			failed: 0,
			id: 4,
			image: null,
			name: "Bot",
			status: "active",
			timezone: null,
			username: "Griddo Bot",
			isSuperAdmin: true,
			roles: [
				{ siteId: "global", roles: [1] },
				{ siteId: "all", roles: [1] },
			],
		},
		currentPermissions: [],
	},
};

describe("IntegrationsField component rendering", () => {
	test("should render the component IntegrationsField", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [];
		const store = mockStore(initialStore);

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} />
				</ThemeProvider>,
				{ store },
			);
		});

		expect(screen.getByText("Add-ons")).toBeTruthy();
	});

	test("should render the component IntegrationsField with integrations", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [...initialStore.integrations.integrations];
		const store = mockStore(initialStore);

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} />
				</ThemeProvider>,
				{ store },
			);
		});

		expect(screen.getAllByTestId("integration-item").length).toBe(4);
	});

	test("should render the component IntegrationsField with custom code integration", async () => {
		const initialState = { ...defaultProps };

		const customOption = {
			name: "",
			contentHead: "",
			contentBody: "",
			contentBodyPosition: null,
			contentPresence: { presenceType: "page-manual", relatedPages: null },
		};

		defaultProps.value = [...initialStore.integrations.integrations, customOption];
		const store = mockStore(initialStore);

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} />
				</ThemeProvider>,
				{ store },
			);
		});

		expect(screen.getAllByTestId("integration-item").length).toBe(5);
	});
});

describe("Events", () => {
	test("should delete a integration", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [...initialStore.integrations.integrations];
		const store = mockStore(initialStore);
		const onChange = jest.fn();

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} onChange={onChange} />
				</ThemeProvider>,
				{ store },
			);
		});

		expect(screen.getAllByTestId("integration-item").length).toBe(4);

		const floatingMenuButtons = screen.getAllByTestId("floating-menu-button");
		fireEvent.click(floatingMenuButtons[1]);
		const actionMenu = screen.getAllByTestId("action-menu-item");
		fireEvent.click(actionMenu[1]);

		const buttonsDefault = screen.getAllByTestId("button-default");
		fireEvent.click(buttonsDefault[buttonsDefault.length - 1]);

		const integrationsWithDeletion = initialStore.integrations.integrations.slice(0, 3);

		expect(onChange).toHaveBeenLastCalledWith(integrationsWithDeletion);
	});

	test("should add an integration", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [];
		const store = mockStore(initialStore);
		const onChange = jest.fn();

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} onChange={onChange} />
				</ThemeProvider>,
				{ store },
			);
		});

		const iconActionComponent = screen.getByTestId("icon-action-component");
		fireEvent.click(iconActionComponent);

		const integrationSideModalOption = screen.getAllByTestId("integration-side-modal-option");
		fireEvent.click(integrationSideModalOption[0]);

		const integrationAdded = initialStore.integrations.integrations.slice(0, 1);

		expect(onChange).toHaveBeenLastCalledWith(integrationAdded);
	});

	test("should add an custom code integration", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [];
		const store = mockStore(initialStore);
		const onChange = jest.fn();

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<ThemeProvider theme={parseTheme(globalTheme)}>
					<IntegrationsField {...{ ...initialState, ...defaultProps }} onChange={onChange} />
				</ThemeProvider>,
				{ store },
			);
		});

		const iconActionComponent = screen.getByTestId("icon-action-component");
		fireEvent.click(iconActionComponent);

		const integrationSideModalOption = screen.getAllByTestId("integration-side-modal-option");
		fireEvent.click(integrationSideModalOption[1]);

		const customOption = {
			active: true,
			name: "",
			contentHead: "",
			contentBody: "",
			contentBodyPosition: null,
			contentPresence: { presenceType: "page-custom", relatedPages: null },
		};

		expect(onChange).toHaveBeenLastCalledWith([customOption]);
	});

	test("should paste a custom code integration", async () => {
		const initialState = { ...defaultProps };
		defaultProps.value = [];
		const _initialStore: any = { ...initialStore };
		_initialStore.integrations.integrationCopy = {
			date: new Date(),
			integration: {
				id: 29,
				name: "My custom integration",
				description: "This is a custom integration",
				site: 86,
				contentHead: "<script>console.log('Hello, world!')</script>",
				contentBody: "",
				contentBodyPosition: "start",
				contentPresence: {
					presenceType: "page-custom",
					relatedPages: null,
				},
				active: true,
			},
		};
		const store = mockStore(initialStore);
		const onChange = jest.fn();

		const data = {
			data: { ...initialStore.integrations },
			status: 200,
			statusText: "Ok",
			headers: {},
			config: {},
		};
		mockedAxios.mockResolvedValue(data);

		await act(async () => {
			render(
				<Router history={history}>
					<ThemeProvider theme={parseTheme(globalTheme)}>
						<IntegrationsField {...{ ...initialState, ...defaultProps }} onChange={onChange} />
					</ThemeProvider>
				</Router>,
				{ store },
			);
		});

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

		expect(onChange).toHaveBeenLastCalledWith([_initialStore.integrations.integrationCopy.integration]);
	});
});
