import { integrations } from "@ax/api";
import { appActions } from "@ax/containers/App";
import { handleRequest } from "@ax/helpers";
import { IIntegration } from "@ax/types";
import { Dispatch } from "redux";

import {
	DEFAULT_PARAMS,
	SET_COPY_INTEGRATION,
	SET_CURRENT_INTEGRATION,
	SET_INTEGRATIONS,
	SET_TOTAL_ITEMS,
} from "./constants";
import { ISetCopyIntegration, ISetCurrentIntegration, ISetIntegrations, ISetTotalItems } from "./interfaces";

function setIntegrations(integrations: IIntegration[]): ISetIntegrations {
	return { type: SET_INTEGRATIONS, payload: { integrations } };
}

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

function setCurrentIntegration(currentIntegration: IIntegration | null): ISetCurrentIntegration {
	return { type: SET_CURRENT_INTEGRATION, payload: { currentIntegration } };
}

function setCopyIntegration(
	integrationCopy: { date: Date; integration: Partial<IIntegration> } | null,
): ISetCopyIntegration {
	return { type: SET_COPY_INTEGRATION, payload: { integrationCopy } };
}

function getIntegrations(site: number, params?: any, skipLoading?: boolean): (dispatch: Dispatch) => Promise<void> {
	return async (dispatch) => {
		try {
			const callback = async () => integrations.getIntegrations(site, params);
			const responseActions = {
				handleSuccess: (response: any) => {
					const { items, totalItems } = response;
					dispatch(setIntegrations(items));
					dispatch(setTotalItems(totalItems));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};
			await handleRequest(callback, responseActions, skipLoading ? [] : [appActions.setIsLoading])(dispatch);
		} catch (e) {
			console.log(e);
		}
	};
}

function resetIntegrations(): (dispatch: Dispatch) => void {
	return (dispatch) => {
		dispatch(setIntegrations([]));
	};
}

function deleteIntegration(
	integrationId: number | number[],
	currentParams?: any,
): (dispatch: any, getState: any) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () =>
				Array.isArray(integrationId)
					? integrations.deleteIntegrationsBulk(integrationId)
					: integrations.deleteIntegration(integrationId);

			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS, ...currentParams };
					dispatch(getIntegrations(currentSiteInfo.id, params));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

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

function changeIntegrationState(
	integrationId: number | number[],
	active: boolean,
	currentParams?: any,
): (dispatch: any, getState: any) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const state = active ? "enable" : "disable";
			const callback = async () =>
				Array.isArray(integrationId)
					? integrations.changeStateBulk(integrationId, state)
					: integrations.changeState(integrationId, state);

			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS, ...currentParams };
					dispatch(getIntegrations(currentSiteInfo.id, params));
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};

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

function getIntegration(id: number, siteID: number): (dispatch: Dispatch) => Promise<void> {
	return async (dispatch) => {
		try {
			const callback = async () => integrations.getIntegration(id, siteID);
			const responseActions = {
				handleSuccess: (response: IIntegration) => setCurrentIntegration(response),
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};
			await handleRequest(callback, responseActions, [appActions.setIsLoading])(dispatch);
		} catch (e) {
			console.log(e);
		}
	};
}

function createIntegration(data: IIntegration, siteID: number): (dispatch: Dispatch) => Promise<boolean> {
	return async (dispatch) => {
		try {
			const callback = async () => integrations.createIntegration(data, siteID);
			const responseActions = {
				handleSuccess: (response: IIntegration) => dispatch(setCurrentIntegration(response)),
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};
			return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function updateIntegration(data: IIntegration, siteID: number): (dispatch: Dispatch) => Promise<boolean> {
	return async (dispatch) => {
		try {
			const callback = async () => integrations.updateIntegration(data, siteID);
			const responseActions = {
				handleSuccess: (response: IIntegration) => dispatch(setCurrentIntegration(response)),
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};
			return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

function copyIntegration(integration: Partial<IIntegration>): (dispatch: Dispatch) => void {
	return (dispatch) => {
		const payload = {
			date: new Date(),
			integration,
		};
		dispatch(setCopyIntegration(payload));
	};
}

function orderIntegration(
	id: number,
	newOrder: number,
	currentParams?: any,
): (dispatch: Dispatch, getState: any) => Promise<boolean> {
	return async (dispatch, getState) => {
		try {
			const {
				sites: { currentSiteInfo },
			} = getState();

			const callback = async () => integrations.orderIntegration(id, newOrder);
			const responseActions = {
				handleSuccess: () => {
					const params = { ...DEFAULT_PARAMS, ...currentParams };
					getIntegrations(currentSiteInfo.id, params)(dispatch);
				},
				handleError: (response: any) => appActions.handleError(response)(dispatch),
			};
			return await handleRequest(callback, responseActions, [appActions.setIsLoading])(dispatch);
		} catch (e) {
			console.log(e);
			return false;
		}
	};
}

export {
	getIntegrations,
	resetIntegrations,
	deleteIntegration,
	changeIntegrationState,
	getIntegration,
	createIntegration,
	updateIntegration,
	setCurrentIntegration,
	copyIntegration,
	orderIntegration,
};
