import { redirects } from "@ax/api";
import { appActions } from "@ax/containers/App";
import { handleRequest } from "@ax/helpers";
import {
	DEFAULT_PARAMS,
	ERROR_CODE,
	SET_IMPORTS,
	SET_REDIRECTS,
	SET_TOTAL_IMPORTS,
	SET_TOTAL_ITEMS,
} from "./constants";
import { ISetImports, ISetRedirects, ISetTotalImports, ISetTotalItems } from "./interfaces";

function setRedirects(redirects: any[]): ISetRedirects {
	return { type: SET_REDIRECTS, payload: { redirects } };
}

function setTotalItems(totalItems: number): ISetTotalItems {
	return { type: SET_TOTAL_ITEMS, payload: { totalItems } };
}

function setImports(imports: any): ISetImports {
	return { type: SET_IMPORTS, payload: { imports } };
}

function setTotalImports(totalImports: number): ISetTotalImports {
	return { type: SET_TOTAL_IMPORTS, payload: { totalImports } };
}

function getRedirects(params: any, filters?: string): (dispatch: any) => Promise<void> {
	return async (dispatch) => {
		try {
			dispatch(setRedirects([]));
			const callback = async () => redirects.getRedirects(params, filters);

			const responseActions = {
				handleSuccess: (response: any) => {
					const { items, totalItems } = response;
					dispatch(setRedirects(items));
					dispatch(setTotalItems(totalItems));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

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

function addRedirect(
	redirect: { from: string; to: string | number },
	errorAction: () => void,
	force?: boolean,
	filter?: string,
): (dispatch: any, getState: any) => Promise<void> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () => redirects.createRedirect(redirect, force);

			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS };
					const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
					dispatch(getRedirects(params, siteFilterQuery));
				},
				handleError: (response: any) => {
					const { status } = response;

					status === ERROR_CODE.isBeingUsed ? errorAction() : appActions.handleError(response)(dispatch);
				},
			};

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

function updateRedirect(
	redirect: { from: string; to: string | number },
	redirectID: number,
	filter?: string,
): (dispatch: any, getState: any) => Promise<void> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () => redirects.updateRedirect(redirect, redirectID);

			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS };
					const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
					dispatch(getRedirects(params, siteFilterQuery));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

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

function deleteRedirect(
	redirectID: number | number[],
	filter?: string,
): (dispatch: any, getState: any) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () =>
				Array.isArray(redirectID) ? redirects.deleteRedirectsBulk(redirectID) : redirects.deleteRedirect(redirectID);

			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS };
					const siteFilterQuery = currentSiteInfo && currentSiteInfo.id ? `&sites=${currentSiteInfo.id}` : filter;
					dispatch(getRedirects(params, siteFilterQuery));
				},
				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);
				},
			};

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

function importRedirects(
	redirect: { from: string; to: string | number }[],
	check: boolean,
): (dispatch: any) => Promise<boolean> {
	return async (dispatch) => {
		try {
			const callback = async () =>
				check ? redirects.createRedirectsBulkCheck(redirect) : redirects.createRedirectsBulk(redirect);

			const responseActions = {
				handleSuccess: (response: any) => {
					if (check) {
						const { total, error, existing, ok } = response;
						dispatch(setImports({ error, existing, ok }));
						dispatch(setTotalImports(total));
					} else {
						const params = { ...DEFAULT_PARAMS };
						dispatch(getRedirects(params));
					}
				},
				handleError: (response: any) => {
					const {
						data: { message },
					} = response;
					const isMultiple = Array.isArray(message) && message.length > 1;
					const msg = isMultiple ? `The import action failed due to ${message.length} errors.` : undefined;
					appActions.handleError(response, isMultiple, msg)(dispatch);
				},
			};

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

export { getRedirects, addRedirect, updateRedirect, deleteRedirect, importRedirects };
