import { Dispatch } from "redux";
import {
	FormCategoriesList,
	FormCategoriesOrderParams,
	FormCategory,
	FormContent,
	FormState,
	GetFormsParams,
	IBreadcrumbItem,
	IModule,
	INotification,
	IRootState,
	ISchema,
	ListForm,
} from "@ax/types";
import {
	deepClone,
	getDefaultFormTemplate,
	getDefaultSchema,
	getImageFromIFrame,
	getSchema,
	handleRequest,
	isReqOk,
} from "@ax/helpers";
import {
	findByEditorID,
	generateEditorIDs,
	getLastComponentEditorID,
	getNewBreadcrumb,
	getParentKey,
	moveElement,
	parseData,
	updateByEditorID,
	updateComponent,
} from "@ax/forms";
import { appActions } from "@ax/containers/App";
import { forms, images } from "@ax/api";
import {
	SET_BREADCRUMB,
	SET_COPY_MODULE,
	SET_CURRENT_FORM_ID,
	SET_FORM_CONTENT,
	SET_FORMS,
	SET_SCHEMA,
	SET_SELECTED_CONTENT,
	SET_SELECTED_EDITOR_ID,
	SET_SELECTED_PARENT,
	SET_TAB,
	SET_TEMPLATE,
	SET_SUMMARY,
	DEFAULT_PARAMS,
	SET_CURRENT_FORM_CATEGORIES,
	SET_IS_NEW_TRANSLATION,
	SET_IS_IA_TRANSLATED,
} from "./constants";
import {
	ISetBreadcrumb,
	ISetCopyModule,
	ISetCurrentFormID,
	ISetFormContent,
	ISetForms,
	ISetSchema,
	ISetSelectedContent,
	ISetSelectedEditorID,
	ISetSelectedParent,
	ISetTab,
	ISetTemplate,
	ISetSummary,
	ISetCurrentFormCategories,
	ISetIsNewTranslation,
	ISetIsIATranslated,
} from "./interfaces";
import { getUpdatedComponents } from "./utils";

const { setIsLoading, setIsSaving, handleError } = appActions;

function setForms(forms: FormContent[]): ISetForms {
	return { type: SET_FORMS, payload: { forms } };
}

function setFormContent(formContent: FormContent | null): ISetFormContent {
	const iframe = document.querySelector("iframe");
	iframe?.contentWindow?.postMessage(
		{
			type: "content-update",
			message: formContent,
		},
		"*",
	);
	return { type: SET_FORM_CONTENT, payload: { formContent } };
}

function setSchema(schema: ISchema | Record<string, never>): ISetSchema {
	return { type: SET_SCHEMA, payload: { schema } };
}

function setTemplate(template: string): ISetTemplate {
	return { type: SET_TEMPLATE, payload: { template } };
}

function setSelectedFormContent(selectedContent: Record<string, unknown>): ISetSelectedContent {
	return { type: SET_SELECTED_CONTENT, payload: { selectedContent } };
}

function setSelectedParent(selectedParent: Record<string, unknown> | null): ISetSelectedParent {
	return { type: SET_SELECTED_PARENT, payload: { selectedParent } };
}

function setSelectedEditorID(selectedEditorID: number): ISetSelectedEditorID {
	return { type: SET_SELECTED_EDITOR_ID, payload: { selectedEditorID } };
}

function setTab(tab: string): ISetTab {
	return { type: SET_TAB, payload: { tab } };
}

function setCurrentFormID(currentFormID: number | null): ISetCurrentFormID {
	return { type: SET_CURRENT_FORM_ID, payload: { currentFormID } };
}

function setBreadcrumb(breadcrumb: IBreadcrumbItem[]): ISetBreadcrumb {
	return { type: SET_BREADCRUMB, payload: { breadcrumb } };
}

function setCopyModule(moduleCopy: { date: Date; elements: IModule[] } | null): ISetCopyModule {
	return { type: SET_COPY_MODULE, payload: { moduleCopy } };
}

function setSummary(summary: { total: number; active: number; inactive: number }): ISetSummary {
	return { type: SET_SUMMARY, payload: { summary } };
}

function setCurrentFormCategories(currentFormCategories: FormCategory[]): ISetCurrentFormCategories {
	return { type: SET_CURRENT_FORM_CATEGORIES, payload: { currentFormCategories } };
}

function setIsNewTranslation(isNewTranslation: boolean): ISetIsNewTranslation {
	return { type: SET_IS_NEW_TRANSLATION, payload: { isNewTranslation } };
}

function setIsIATranslated(isIATranslated: boolean): ISetIsIATranslated {
	return { type: SET_IS_IA_TRANSLATED, payload: { isIATranslated } };
}

function getForms(
	siteID: number | null,
	params?: GetFormsParams,
	loading = true,
): (dispatch: Dispatch) => Promise<void> {
	return async (dispatch) => {
		try {
			const getParams = { ...DEFAULT_PARAMS, ...params };

			const site = siteID ? siteID : "global";

			const responseActions = {
				handleSuccess: (response: ListForm) => {
					const { items, totalItems, active, inactive } = response;
					dispatch(setForms(items));
					dispatch(setSummary({ total: totalItems, active, inactive }));
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			const callback = async () => forms.getForms(site, getParams);

			const loadingAction = loading ? [setIsLoading] : [];

			await handleRequest(callback, responseActions, loadingAction)(dispatch);
		} catch (e) {
			console.log(e);
		}
	};
}

function getForm(formID: number | null): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
	return async (dispatch, getState) => {
		try {
			dispatch(setIsLoading(true));
			const {
				forms: { isNewTranslation },
			} = getState();

			if (formID) {
				const response: { status: number; data: FormContent } = await forms.getForm(formID);

				if (isReqOk(response.status)) {
					addTemplate(response.data.template.templateType)(dispatch);
					dispatch(setSelectedEditorID(0));
					const formData: Partial<FormContent> = response.data;
					if (isNewTranslation) {
						delete formData.id;
						formData.state = "inactive";
						formData.canBeTranslated = true;
						formData.originalLanguage = formData.language;
						formData.formInUse = null;
					}
					generateFormContent(formData)(dispatch, getState);
					dispatch(setCurrentFormID(response.data.id));
					dispatch(setIsIATranslated(false));
				}
			} else {
				generateNewForm()(dispatch, getState);
			}
		} catch (e) {
			dispatch(setIsLoading(false));
			console.log(e); // TODO: capturar error bien
		}
	};
}

function generateNewForm(): (dispatch: Dispatch, getState: () => IRootState) => void {
	return async (dispatch, getState) => {
		const {
			forms: { template },
			app: { lang },
		} = getState();

		let form = getDefaultSchema("FormPage");
		const parsedPageData = parseData(form, true);
		const currentTemplate = getDefaultFormTemplate(template);

		form = { ...parsedPageData, template: currentTemplate, language: lang.id, dataLanguages: [] };

		dispatch(setIsNewTranslation(false));

		// SET PAGE AS ROOT WHEN NEW PAGE
		dispatch(setSelectedEditorID(0));
		generateFormContent(form)(dispatch, getState);
	};
}

function generateFormContent(
	formContent: Partial<FormContent>,
): (dispatch: Dispatch, getState: () => IRootState) => void {
	return (dispatch, getState) => {
		const {
			forms: { selectedEditorID },
			sites: { currentSiteInfo },
		} = getState();

		const { pageContent } = generateEditorIDs({ ...formContent });
		pageContent["site"] = currentSiteInfo ? currentSiteInfo.id : null;
		const { element: selectedContent, parent: selectedParent } = findByEditorID(pageContent, selectedEditorID);
		const { component } = selectedContent;
		const schema = getSchema(component);
		if (!schema) return;
		dispatch(setSchema(schema));
		dispatch(setFormContent(pageContent));
		updateBreadcrumb(selectedEditorID)(dispatch, getState);
		dispatch(setSelectedFormContent(selectedContent));
		dispatch(setSelectedParent(selectedParent));
		dispatch(setIsLoading(false));
	};
}

function setSelectedContent(editorID: number): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
	return async (dispatch, getState) => {
		const {
			forms: { formContent, tab },
		} = getState();

		dispatch(setIsLoading(true));

		const iframe = document.querySelector("iframe");
		iframe?.contentWindow?.postMessage(
			{
				type: "selected-content",
				message: editorID,
			},
			"*",
		);

		if (editorID > 0) {
			localStorage.setItem("selectedID", `${editorID}`);
		}

		const { element: selectedContent, parent: selectedParent } = findByEditorID({ formContent }, editorID);

		const { component } = selectedContent;
		const defaultSchema = getDefaultSchema(component);

		// if schema default has new keys
		const isUpdatedComponent = Object.keys(defaultSchema).length + 2 !== Object.keys(selectedContent).length;
		isUpdatedComponent && updateComponent(selectedContent, defaultSchema);

		const schema = getSchema(component);
		if (!schema) return;
		const defaultTab = "content";
		dispatch(setTab(tab || defaultTab));
		dispatch(setSchema(schema));
		dispatch(setSelectedEditorID(editorID));
		updateBreadcrumb(editorID)(dispatch, getState);
		dispatch(setSelectedFormContent({ ...selectedContent }));
		dispatch(setSelectedParent(selectedParent));
		dispatch(setIsLoading(false));
	};
}

function updateFormContent(
	selectedEditorID: number,
	key: string,
	value: any,
): (dispatch: Dispatch, getState: () => IRootState) => void {
	return (dispatch, getState) => {
		const {
			forms: { formContent, selectedContent },
		} = getState();

		const clonedContent = deepClone(formContent);

		const updatedSelectedContent = updateByEditorID(selectedContent, selectedEditorID, key, value);
		const updatedFormContent = updateByEditorID(clonedContent, selectedEditorID, key, value);

		dispatch(setSelectedFormContent(updatedSelectedContent));
		dispatch(setFormContent(updatedFormContent));

		if (value && typeof value === "object") {
			generateFormContent(updatedFormContent)(dispatch, getState);
		}
	};
}

function updateBreadcrumb(editorID: number): (dispatch: Dispatch, getState: any) => void {
	return (dispatch, getState) => {
		const {
			forms: { formContent },
		}: IRootState = getState();

		const newBreadcrumb = getNewBreadcrumb(formContent, editorID, false);

		dispatch(setBreadcrumb(newBreadcrumb));
	};
}

function saveForm(
	formHtml?: HTMLDivElement | null,
	updateState?: FormState,
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				forms: { formContent },
				app: { lang },
			} = getState();

			if (!formContent) {
				return false;
			}

			const isNewForm = !formContent.id;
			formContent["language"] = lang.id;

			const callback = async () =>
				isNewForm ? await forms.createForm(formContent) : await forms.updateForm(formContent.id, formContent);

			const responseActions = {
				handleSuccess: async (response: FormContent) => {
					const { pageContent } = generateEditorIDs(response);
					if (updateState) {
						const isUpdated = await forms.updateFormState(pageContent.id, updateState);
						if (isUpdated) {
							pageContent["state"] = updateState;
						}
					}
					if (isNewForm) {
						dispatch(setCurrentFormID(pageContent.id));
					}
					dispatch(setFormContent(pageContent));
					dispatch(setIsNewTranslation(false));

					if (formHtml) {
						const form = new FormData();
						const image = await getImageFromIFrame(formHtml, "form-thumbnail");

						if (image) {
							form.append("file", image);
							images.createThumbnail(pageContent.id, "form", form);
						}
					}
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			return await handleRequest(callback, responseActions, [setIsSaving])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function deleteForm(id: number | number[]): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const responseActions = {
				handleSuccess: () => {
					getForms(currentSiteInfo?.id || null)(dispatch);
				},
				handleError: (response: any) => {
					const {
						data: { message },
					} = response;
					const isMultiple = Array.isArray(message) && message.length > 1;
					const msg = isMultiple ? `The delete action failed due to ${message.length} errors.` : undefined;
					appActions.handleError(response, isMultiple, msg)(dispatch);
				},
			};

			const callback = async () => (Array.isArray(id) ? await forms.deleteFormBulk(id) : await forms.deleteForm(id));

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function updateFormState(
	formID: number | number[],
	state: FormState,
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () =>
				Array.isArray(formID)
					? await forms.updateFormStateBulk(formID, state)
					: await forms.updateFormState(formID, state);

			const responseActions = {
				handleSuccess: () => {
					getForms(currentSiteInfo?.id || null)(dispatch);
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function setSelectedTab(tab: string): (dispatch: Dispatch) => void {
	return (dispatch) => {
		try {
			dispatch(setTab(tab));
		} catch (e) {
			console.log("Error", e);
		}
	};
}

function addModule(type: string, key: string): (dispatch: Dispatch, getState: () => IRootState) => void {
	return (dispatch, getState) => {
		const {
			forms: { formContent, selectedEditorID: editorID },
		} = getState();

		if (!formContent) return;

		const templateContent = formContent.template;

		const component = {
			editorID: editorID === 0 ? templateContent?.editorID : editorID,
			type,
		};

		const updatedObj = getUpdatedComponents(templateContent, component, key);

		const updatedPageContent = {
			...formContent,
			template: {
				...templateContent,
				...updatedObj,
			},
		};

		generateFormContent(updatedPageContent)(dispatch, getState);

		const {
			forms: { formContent: generatedFormContent },
		}: IRootState = getState();

		if (!generatedFormContent) return;

		const lastElementEditorID = getLastComponentEditorID(generatedFormContent.template, component.editorID, key);
		localStorage.setItem("selectedID", `${lastElementEditorID}`);
	};
}

function deleteModule(editorID: number[], key?: string): (dispatch: Dispatch, getState: () => IRootState) => void {
	return (dispatch, getState) => {
		const {
			forms: { formContent },
		} = getState();

		if (!formContent) return;

		const templateContent = formContent.template;

		const { parent, grandParent } = findByEditorID(templateContent, editorID[0]);
		const parentModule = Array.isArray(parent) ? grandParent : parent;

		const parentKey = key ? key : getParentKey(parentModule, editorID[0]);
		const itemsArr = parentModule[parentKey];

		editorID.forEach((moduleID) => {
			const index = itemsArr.findIndex((module: IModule) => module.editorID === moduleID);
			itemsArr.splice(index, 1);
		});

		const updatedContent = {
			...formContent,
			template: {
				...templateContent,
			},
		};

		generateFormContent(updatedContent)(dispatch, getState);
	};
}

function duplicateModule(editorID: number[], key?: string): (dispatch: Dispatch, getState: () => IRootState) => number {
	return (dispatch, getState) => {
		const {
			forms: { formContent },
		} = getState();

		if (!formContent) return;

		const templateContent = formContent.template;

		const { parent, grandParent } = findByEditorID(templateContent, editorID[0]);
		const parentModule = Array.isArray(parent) ? grandParent : parent;

		const parentKey = key ? key : getParentKey(parentModule, editorID[0]);
		const itemsArr = parentModule[parentKey];
		let duplicatedItemIndex = 0;

		editorID.forEach((id) => {
			const { element: originalItem } = findByEditorID(templateContent, id);
			const clonedItem = deepClone(originalItem);
			delete clonedItem.fixed;
			const originalItemIndex = itemsArr.findIndex((module: IModule) => module.editorID === id);
			duplicatedItemIndex = originalItemIndex + 1;
			itemsArr.splice(duplicatedItemIndex, 0, clonedItem);
		});

		const updatedContent = {
			...formContent,
			template: {
				...templateContent,
			},
		};

		generateFormContent(updatedContent)(dispatch, getState);

		const {
			forms: { formContent: generatedFormContent },
		}: IRootState = getState();

		const { parent: generatedParent, grandParent: generatedGrandParent } = findByEditorID(
			generatedFormContent,
			editorID[0],
		);
		const module = Array.isArray(generatedParent) ? generatedGrandParent : generatedParent;
		const duplicatedEditorID = module[parentKey][duplicatedItemIndex].editorID;

		localStorage.setItem("selectedID", `${duplicatedEditorID}`);

		return duplicatedEditorID;
	};
}

function moveModule(
	elementID: number[],
	content: any,
	newIndex: number,
	key: string,
): (dispatch: Dispatch, getState: () => IRootState) => void {
	return async (dispatch, getState) => {
		const {
			forms: { formContent, selectedContent },
		} = getState();

		if (!formContent) return;

		const templateContent = formContent.template;
		const isRoot = selectedContent.component === "FormPage";

		const contentElements = isRoot ? [...selectedContent.template[key]] : [...selectedContent[key]];
		const editorID = isRoot ? templateContent.editorID : selectedContent.editorID;

		const { element: selectedModule } = findByEditorID(templateContent, editorID);

		selectedModule[key] = moveElement(elementID, contentElements, newIndex);

		const updatedContent = {
			...formContent,
			template: {
				...templateContent,
			},
		};

		dispatch(setFormContent(updatedContent));
		dispatch(setSelectedFormContent(isRoot ? updatedContent : selectedModule));
	};
}

function copyModule(editorID: number[]): (dispatch: Dispatch, getState: () => IRootState) => boolean | number {
	return (dispatch, getState) => {
		const {
			forms: { formContent },
		} = getState();

		if (!formContent) return false;

		const templateContent: any = formContent.template;
		const modulesToCopy: IModule[] = [];

		editorID.forEach((id) => {
			const { element: originalElement } = findByEditorID(templateContent, id);
			if (originalElement) {
				// biome-ignore lint/correctness/noUnusedVariables: TODO: fix this
				const { editorID, parentEditorID, ...element } = originalElement;
				delete element.fixed;
				modulesToCopy.push(element);
			}
		});

		if (modulesToCopy.length) {
			const payload = {
				date: new Date(),
				elements: modulesToCopy,
			};

			dispatch(setCopyModule(payload));
			return payload.elements.length;
		} else {
			return false;
		}
	};
}

function pasteModule(
	editorID: number,
	key: string,
	modulesToPaste: IModule[],
): (dispatch: Dispatch, getState: () => IRootState) => Promise<{ error?: INotification }> {
	return async (dispatch, getState) => {
		const {
			forms: { formContent },
		} = getState();

		if (!formContent) return { error: undefined };

		const templateContent = formContent.template;
		const { element: originalElement } = findByEditorID(templateContent, editorID);
		const itemsArr = originalElement[key];

		modulesToPaste.forEach((element) => {
			const validatedModuleCopy = deepClone(element);
			itemsArr.push(validatedModuleCopy);
		});

		const updatedPageContent = {
			...formContent,
		};

		generateFormContent(updatedPageContent)(dispatch, getState);

		return { error: undefined };
	};
}

function addTemplate(template: string): (dispatch: Dispatch) => Promise<void> {
	return async (dispatch) => {
		try {
			dispatch(setTemplate(template));
		} catch (e) {
			console.log("Error", e);
		}
	};
}

function resetForm(): (dispatch: Dispatch) => void {
	return async (dispatch) => {
		dispatch(setCurrentFormID(null));
		dispatch(setFormContent(null));
		dispatch(setSchema({}));
	};
}

function getFormCategories(type: string): (dispatch: Dispatch, getState: () => IRootState) => Promise<void> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const siteID = currentSiteInfo ? currentSiteInfo.id : "global";

			const responseActions = {
				handleSuccess: (response: FormCategoriesList) => {
					const { items } = response;
					dispatch(setCurrentFormCategories(items));
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			const callback = async () => forms.getFormCategories(siteID, type);

			await handleRequest(callback, responseActions, [setIsLoading])(dispatch);
		} catch (e) {
			console.log(e);
		}
	};
}

function createFormCategory(
	content: { title: string; code: string },
	categoryType: string,
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const relatedSite = currentSiteInfo ? currentSiteInfo.id : null;

			const callback = async () =>
				await forms.createFormCategory({
					categoryType,
					content,
					relatedSite,
				});

			const responseActions = {
				handleSuccess: () => {
					getFormCategories(categoryType)(dispatch, getState);
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			return await handleRequest(callback, responseActions, [setIsSaving])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function updateFormCategory(
	id: number,
	content: { title: string; code: string },
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const callback = async () => await forms.updateFormCategory(id, { content });

			const responseActions = {
				handleSuccess: (result: FormCategory) => {
					getFormCategories(result.categoryType)(dispatch, getState);
				},
				handleError: (response: any) => handleError(response)(dispatch),
			};

			return await handleRequest(callback, responseActions, [setIsSaving])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function deleteFormCategory(
	id: number | number[],
	categoryType: string,
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const responseActions = {
				handleSuccess: () => {
					getFormCategories(categoryType)(dispatch, getState);
				},
				handleError: (response: any) => {
					const {
						data: { message },
					} = response;
					const isMultiple = Array.isArray(message) && message.length > 1;
					const msg = isMultiple ? `The delete action failed due to ${message.length} errors.` : undefined;
					appActions.handleError(response, isMultiple, msg)(dispatch);
				},
			};

			const callback = async () =>
				Array.isArray(id) ? forms.deleteFormCategoryBulk(id) : forms.deleteFormCategory(id);

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function orderFormCategory(
	data: FormCategoriesOrderParams,
): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const responseActions = {
				handleSuccess: () => getFormCategories(data.categoryType)(dispatch, getState),
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

			const callback = async () => forms.orderFormCategory(data);

			return await handleRequest(callback, responseActions, [setIsLoading])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function createNewTranslation(isNewTranslation: boolean): (dispatch: Dispatch) => void {
	return async (dispatch) => {
		try {
			dispatch(setIsNewTranslation(isNewTranslation));
		} catch (e) {
			console.log(e);
		}
	};
}

function getFormTranslation(langID: number): (dispatch: Dispatch, getState: () => IRootState) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				forms: { formContent },
			}: IRootState = getState();

			const responseActions = {
				handleSuccess: (data: FormContent) => {
					data["canBeTranslated"] = false;
					generateFormContent(data)(dispatch, getState);
					dispatch(setIsIATranslated(true));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

			const callback = async () => formContent && forms.getFormTranslation(formContent, langID);

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function duplicateForm(formID: number, title: string): (dispatch: Dispatch) => Promise<boolean> {
	return async (dispatch) => {
		try {
			const responseActions = {
				handleSuccess: (data: FormContent) => {
					dispatch(setCurrentFormID(data.id));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

			const callback = async () => forms.duplicateForm(formID, title);

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function copyForm(formID: number, siteID: number): (dispatch: Dispatch) => Promise<boolean> {
	return async (dispatch) => {
		try {
			const responseActions = {
				handleSuccess: () => {},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

			const callback = async () => forms.copyForm(formID, siteID);

			return await handleRequest(callback, responseActions, [])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

export {
	setSelectedTab,
	setFormContent,
	setCurrentFormID,
	getForms,
	getForm,
	updateFormContent,
	setSelectedContent,
	addModule,
	deleteModule,
	duplicateModule,
	moveModule,
	copyModule,
	pasteModule,
	addTemplate,
	saveForm,
	resetForm,
	deleteForm,
	getFormCategories,
	createFormCategory,
	updateFormCategory,
	deleteFormCategory,
	orderFormCategory,
	updateFormState,
	createNewTranslation,
	getFormTranslation,
	setIsIATranslated,
	duplicateForm,
	copyForm,
};
