import { __awaiter, __rest } from "tslib";
/* eslint-disable fp/no-let */
import React from "react";
import { RuntimeContext, useTracking, useClient, useCurrentUser, useEvaluateLazy, } from "@qorebase/app-component";
import { useLocation, useNavigate } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import { useComposer } from "../Composer";
import { EditorToastNotificationContext } from "../EditorToastNotification";
import { useNavigations } from "../hooks/navigations";
import qore from "../hooks/qore";
import aixp from "../integrations/aixp";
import { useQRScannerAction } from "../QRScanner.action";
import { ToastNotificationContext } from "../ToastNotification";
import { boxed } from "../utils/boxed";
import { objectMap } from "../utils/objectMap";
import { omit } from "../utils/omit";
import * as queryString from "../utils/query-string";
import { useRefreshDataContext } from "./useRefreshData";
export const useActionTrigger = (action, row, source) => {
    const { code } = useQRScannerAction();
    const { trackEvent } = useTracking();
    const navigate = useNavigate();
    const location = useLocation();
    const { navigations: navs } = useNavigations();
    const firstNav = navs[0];
    const [state, setState] = React.useState({
        loading: false,
    });
    const evaluate = useEvaluateLazy();
    const composer = useComposer();
    const config = RuntimeContext.useSelectState((state) => state.config);
    const client = useClient();
    const sdk = qore.useSDK();
    const actionValues = boxed(action);
    const currentTable = RuntimeContext.useSelectState((state) => {
        const view = state.schema.views.find((view) => view.name === source.target);
        return state.schema.tables.find((table) => view ? table.name === view.query.table : table.name === source.target);
    });
    const { triggerNotification } = React.useContext(ToastNotificationContext);
    const { triggerNotification: editorTriggerNotification } = React.useContext(EditorToastNotificationContext);
    const { triggerQRScanner } = useQRScannerAction();
    const { refetch: refetchUser } = useCurrentUser();
    const loggedInPage = RuntimeContext.useSelectState((state) => { var _a; return (_a = state.config.initialPage) === null || _a === void 0 ? void 0 : _a.loggedInPage; });
    const aixpIntegration = aixp.useIntegration();
    const { refreshData } = useRefreshDataContext();
    const handleClick = React.useCallback((action, additionalValues = {}, opts) => __awaiter(void 0, void 0, void 0, function* () {
        var _a, _b;
        switch (action.type) {
            case "open_link":
                window.open(evaluate(action.link, additionalValues), "_blank");
                return;
            case "logout":
                localStorage.removeItem(`${config.projectID}_user_token`);
                refetchUser();
                navigate(`/page/login`);
                return;
            case "back_to_login":
                composer.forward("/page/login?redirectRoot=1", {
                    state: {
                        // @ts-ignore
                        direction: "slideLeft",
                    },
                });
                return;
            case "refresh_data":
                refreshData();
                return;
            case "jump_to_page":
            case "view_detail": {
                if (!action.pageID)
                    return;
                const event = action.eventName || action.type;
                trackEvent({
                    data: {
                        event,
                        properties: row,
                    },
                });
                const params = objectMap(Object.assign({ rowId: action.rowID }, action.params), (expression) => evaluate(expression !== null && expression !== void 0 ? expression : "", additionalValues));
                const locationQuery = queryString.parse(location.search);
                if ((locationQuery === null || locationQuery === void 0 ? void 0 : locationQuery.modalPage) &&
                    (opts === null || opts === void 0 ? void 0 : opts.calledBy) !== "close_page_modal") {
                    const { rowId } = params;
                    const query = queryString.stringify(Object.assign(Object.assign({}, locationQuery), { modalPage: action.pageID, modalRowId: rowId }));
                    const path = `${location.pathname}?${query}`;
                    composer.forward(path, {
                        modalPage: true,
                    });
                }
                else {
                    composer.forward(`/page/${action.pageID}?${queryString.stringify(params)}`, {
                        state: {
                            // @ts-ignore
                            allowBackNav: action.allowBackNavigation,
                            // @ts-ignore
                            direction: action.direction,
                        },
                    });
                }
                return;
            }
            case "trigger_action":
                if (source.type !== "record")
                    return;
                setState((state) => (Object.assign(Object.assign({}, state), { loading: true })));
                try {
                    const column = currentTable === null || currentTable === void 0 ? void 0 : currentTable.columns.find((column) => column.name === action.actionName);
                    const payload = action.payload || {};
                    const customPayload = Object.keys(payload).reduce((params, key) => {
                        const evaluated = evaluate(payload[key] || "", additionalValues);
                        return Object.assign(Object.assign({}, params), { [key]: evaluated });
                    }, {});
                    const data = { args: customPayload || {} };
                    const actionUrl = `/v1/action/${currentTable.name}/${column.name}/${source.defaultRow.type === "row-id"
                        ? source.rowId || source.defaultRow.rowId
                        : source.rowId || additionalValues.id}`;
                    const response = yield client.project.axios.post(actionUrl, data, {
                        baseURL: client.project.config.endpoint,
                        responseType: 
                        // @ts-ignore
                        column.definition.action === "Print" ? "blob" : undefined,
                        headers: {
                            accept: 
                            // @ts-ignore
                            column.definition.action === "JavaScript"
                                ? "application/json, text/plain, */*"
                                : "application/pdf",
                        },
                    });
                    // @ts-ignore
                    if (column.definition.action === "Print") {
                        // @ts-ignore
                        const url = window.URL.createObjectURL(new Blob([response.data]));
                        const link = document.createElement("a");
                        link.href = url;
                        link.setAttribute("download", `${(source.defaultRow.type === "row-id"
                            ? source.rowId || source.defaultRow.rowId
                            : source.rowId) || additionalValues.id}-${column.name}-${new Date().toISOString()}.pdf`); //or any other extension
                        document.body.appendChild(link);
                        link.click();
                    }
                    const event = action.eventName || action.type;
                    trackEvent({
                        data: {
                            event,
                            properties: row,
                        },
                    });
                    handleClick(action.onSuccess);
                    if (action.showNotification && response.data) {
                        triggerNotification(Object.assign({ variant: "success" }, action.notification.onSuccess));
                    }
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                    return {
                        "response.statusCode": response.status,
                        "response.message": ((_a = response.data) === null || _a === void 0 ? void 0 : _a.result) || "",
                    };
                }
                catch (e) {
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                    handleClick(action.onFail);
                    if (action.showNotification) {
                        triggerNotification(Object.assign({ variant: "error" }, action.notification.onFail));
                    }
                    throw new Error(e);
                }
            case "trigger_pipeline":
                setState((state) => (Object.assign(Object.assign({}, state), { loading: true })));
                try {
                    const customPayload = Object.keys(action.payload).reduce((params, key) => {
                        const evaluated = evaluate(action.payload[key] || "", additionalValues);
                        return Object.assign(Object.assign({}, params), { [key]: evaluated });
                    }, {});
                    const endpoint = `${action.pipelineEndpoint}/api/workflow/${action.pipelineID}/instance/${action.triggerID}/inbound`;
                    const resp = yield fetch(endpoint, {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify(customPayload),
                    });
                    const message = yield resp.clone().text();
                    const data = yield resp.json();
                    if (action.showNotification && !!(data === null || data === void 0 ? void 0 : data.success)) {
                        triggerNotification(Object.assign({ variant: "success" }, action.notification.onSuccess));
                    }
                    if (data === null || data === void 0 ? void 0 : data.tracingID) {
                        editorTriggerNotification({
                            variant: "success",
                            tracingID: data.tracingID,
                        }, 10000);
                    }
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                    return {
                        "response.statusCode": resp.status,
                        "response.message": message,
                    };
                }
                catch (error) {
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                    if (action.showNotification) {
                        triggerNotification(Object.assign({ variant: "error" }, action.notification.onFail));
                    }
                    editorTriggerNotification({
                        variant: "error",
                    }, 10000);
                    throw new Error(error);
                }
            case "scan_QR_code":
                triggerQRScanner(action.variableOutput, { message: action.message }, boxed(action.onSuccess));
                return;
            case "open_as_modal": {
                const params = objectMap(Object.assign({ modalRowId: (_b = action === null || action === void 0 ? void 0 : action.params) === null || _b === void 0 ? void 0 : _b.rowId }, action.params), (expression) => evaluate(expression !== null && expression !== void 0 ? expression : "", additionalValues));
                const parsedQuery = queryString.parse(location.search);
                const params_ = __rest(params, []);
                const stringQuery = queryString.stringify(Object.assign(Object.assign(Object.assign({}, parsedQuery), { modalPage: action.pageID }), params_));
                const path = `${location.pathname}?${stringQuery}`;
                composer.setModalPageHistoryLength(0);
                composer.forward(path, {
                    state: {
                        direction: action.direction,
                        modalH: action.height,
                    },
                });
                return;
            }
            case "close_page_modal": {
                const closePageModalParsedQuery = omit(["modalPage", "modalRowId", "modalH"], queryString.parse(location.search));
                const closePageModalStringQuery = queryString.stringify(closePageModalParsedQuery);
                const closePageModalPath = `${location.pathname}?${closePageModalStringQuery}`;
                composer.setModalPageHistoryLength(0);
                composer.forward(closePageModalPath, {});
                handleClick(action.onClose, {}, {
                    calledBy: "close_page_modal",
                });
                return;
            }
            case "show_toast": {
                triggerNotification({
                    variant: action.status,
                    title: evaluate(action.title, additionalValues),
                    description: evaluate(action.subtitle, additionalValues),
                });
                return;
            }
            case "login": {
                setState((state) => (Object.assign(Object.assign({}, state), { loading: true })));
                try {
                    const token = yield client.authenticate(evaluate(action.username, additionalValues), evaluate(action.password, additionalValues));
                    localStorage.setItem(`${config.projectID}_user_token`, token);
                    const { user } = yield refetchUser();
                    aixpIntegration.run((integration) => {
                        integration.identify({
                            userId: user.id,
                            anonymousId: uuidv4(),
                            traits: user,
                        });
                        integration.track({
                            userId: user.external_id,
                            anonymousId: uuidv4(),
                            event: "login",
                            properties: Object.assign(Object.assign({}, user), { role: user.role.name }),
                            context: {
                                traits: user,
                            },
                        });
                    });
                    if (user && location.pathname === "/page/login") {
                        const { redirectRoot } = queryString.parse(location.search);
                        const { nextPage } = queryString.parse(location.search);
                        const url = loggedInPage ? `/page/${loggedInPage}` : nextPage;
                        url && !redirectRoot ? navigate(url) : navigate("/");
                    }
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                }
                catch (errors) {
                    setState((state) => (Object.assign(Object.assign({}, state), { loading: false })));
                    throw new Error(errors);
                }
                return;
            }
            case "request_recover_account": {
                const identifier = evaluate(action.identifier, additionalValues);
                const redirectPage = `${window.location.origin}/page/${action.redirectPage}`;
                yield sdk.recovery({
                    identifier,
                }, redirectPage);
                return;
            }
            case "recover_account": {
                const token = evaluate(action.token, additionalValues);
                const newPassword = evaluate(action.password, additionalValues);
                yield sdk.submitPassword(token, { newPassword });
                return;
            }
            case "none":
            default:
                return;
        }
    }), [
        action,
        history,
        source,
        row,
        composer,
        firstNav,
        evaluate,
        config.projectID,
        location,
    ]);
    const sequentialActionsOnHandleClick = React.useCallback((additionalValues) => {
        actionValues
            .reduce((prevPromise, action) => __awaiter(void 0, void 0, void 0, function* () {
            const values = yield prevPromise;
            const nextValues = yield handleClick(action, values);
            return Object.assign(Object.assign({}, values), nextValues);
        }), Promise.resolve(additionalValues))
            .catch(() => {
            var _a;
            return actionValues[0].type === "none" &&
                ((_a = actionValues[0].onError) === null || _a === void 0 ? void 0 : _a.length) &&
                actionValues[0].onError.reduce((prevPromise, action) => __awaiter(void 0, void 0, void 0, function* () {
                    const values = yield prevPromise;
                    const nextValues = yield handleClick(action, values);
                    return Object.assign(Object.assign({}, values), nextValues);
                }), Promise.resolve(additionalValues));
        });
    }, [actionValues, handleClick]);
    return React.useMemo(() => (Object.assign(Object.assign({}, state), { handleClick: () => sequentialActionsOnHandleClick(), handleClickWithAdditionValues: (additionalValues) => sequentialActionsOnHandleClick(additionalValues) })), [state, handleClick]);
};
//# sourceMappingURL=useActionTrigger.js.map