import { makeStyles } from '@material-ui/core';
import { Skeleton } from '@material-ui/lab';
import { useSnackbar } from 'notistack';
import PropTypes from 'prop-types';
import React, { useCallback, useMemo, useState } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { useTranslation } from 'react-i18next';
import { ConfigService } from '../configService';
import { ActionForm } from './ActionForm';
import { getPathObject } from '../utilities/maintenanceEngine/CrudBrowserUtilities';
import { getSuccessAction } from '../UI/SuccessAction';
import { LayoutUnit } from '../layout/LayoutUnit';
import { NodeActionEnums } from '../enums/unitySystemEnums';
import { SideSheet } from '../UI/surfaces/SideSheet';
import { useActions } from '../hooks/useActions';
import { useUser } from '../utilities/auth/useUser';
import { useAxiosGet } from '../utilities/useAxiosGet';
import { PageContainer } from '../page/PageContainer';
import { useActionStore } from '../stores/actionStore';
const useStyles = makeStyles((theme) => ({
    root: {}
}));
export const ActionSideSheet = (props) => {
    var _a, _b;
    const { open, action, actionPanel, selectedNodeObj, executeAction, selectedEntity, handleOnClose, entityAttributes, foreignKeyData, loadingContent, fetchEntityData, skeleton, showError, crudTableEditionData, crudTableFormData, selectedNode, selectedNodeParent, refreshTree, udpFieldInfos } = props;
    const classes = useStyles();
    const [width, setWidth] = useState(600);
    const [buttonLabel, setButtonLabel] = useState('');
    const [onSubmit, setOnSubmit] = useState(() => () => console.warn('onSubmit not set'));
    const [additionalOnClose, setAdditionalOnClose] = useState();
    const [otherSideSheetProps, setOtherSideSheetProps] = useState({});
    const { enqueueSnackbar, closeSnackbar } = useSnackbar();
    const successAction = getSuccessAction(closeSnackbar);
    const { t } = useTranslation();
    const user = useUser();
    const setSelectedNodeForStore = useActionStore((state) => state.setSelectedNode);
    const selectedNodeFromStore = useActionStore((state) => state.selectedNode);
    const promotedMethodPageId = useMemo(() => {
        var _a, _b;
        if (action === null || action === void 0 ? void 0 : action.value) {
            if (((_a = selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseUpdateMethod) === null || _a === void 0 ? void 0 : _a.apiMethodId) === action.value) {
                return selectedEntity.unityBaseUpdateMethod.pageId;
            }
            else if (((_b = selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseCreateMethod) === null || _b === void 0 ? void 0 : _b.apiMethodId) === action.value) {
                return selectedEntity.unityBaseCreateMethod.pageId;
            }
        }
        return '';
    }, [selectedEntity, action]);
    const [{ data: page, loading: loadingPage }] = useAxiosGet(ConfigService.tenantV1ApiUrl, `page/${((_a = action === null || action === void 0 ? void 0 : action.parameters) === null || _a === void 0 ? void 0 : _a.pageId) || promotedMethodPageId}`, {}, !!!((_b = action === null || action === void 0 ? void 0 : action.parameters) === null || _b === void 0 ? void 0 : _b.pageId) && !!!promotedMethodPageId, false);
    const onCreate = useCallback(async (data) => {
        if ((selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseCreateMethod) && (action === null || action === void 0 ? void 0 : action.value)) {
            if (selectedEntity.unityBaseCreateMethod.apiMethodId === action.value) {
                return await executeAction(data, action.value);
            }
            else {
                showError();
            }
        }
    }, [action, executeAction, selectedEntity, showError]);
    const onUpdate = useCallback(async (data) => {
        if ((selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseUpdateMethod) && (action === null || action === void 0 ? void 0 : action.value)) {
            if (selectedEntity.unityBaseUpdateMethod.apiMethodId === action.value) {
                return await executeAction(data, action.value);
            }
            else {
                showError();
            }
        }
    }, [action, executeAction, selectedEntity, showError]);
    const handleFetchEntityData = useCallback(async () => {
        if (selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseGetAllMethod) {
            const data = {};
            const response = await fetchEntityData({ data }).catch((res) => {
                enqueueSnackbar(res.message, {
                    variant: 'error',
                    anchorOrigin: {
                        vertical: 'top',
                        horizontal: 'center'
                    }
                });
            });
            if ((response === null || response === void 0 ? void 0 : response.status) === 200 && selectedNodeObj) {
                const updatedNode = response.data.find((d) => d.id === selectedNodeObj.id);
                const updatedSelectedNode = Object.assign({}, selectedNodeFromStore);
                updatedSelectedNode.nodeObj = updatedNode;
                setSelectedNodeForStore(updatedSelectedNode);
            }
        }
    }, [
        enqueueSnackbar,
        fetchEntityData,
        selectedEntity,
        selectedNodeObj,
        setSelectedNodeForStore,
        selectedNodeFromStore
    ]);
    const handleOnCreate = useCallback(async (values) => {
        if (selectedEntity && (selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseCreateMethod)) {
            const entityName = selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.entityName;
            if (selectedEntity.unityBaseCreateMethod) {
                const data = { requestBody: values };
                const response = await onCreate({ data }).catch((res) => {
                    enqueueSnackbar(res.message, {
                        variant: 'error',
                        anchorOrigin: {
                            vertical: 'top',
                            horizontal: 'center'
                        }
                    });
                });
                if ((response === null || response === void 0 ? void 0 : response.status) === 200) {
                    enqueueSnackbar(entityName
                        ? t(`${entityName} has been created`)
                        : t(`Entity has been created`), {
                        anchorOrigin: {
                            vertical: 'top',
                            horizontal: 'center'
                        },
                        action: successAction
                    });
                }
            }
        }
        else {
            enqueueSnackbar(t(`Unable to retrieve entity methods`), {
                variant: 'error',
                anchorOrigin: {
                    vertical: 'top',
                    horizontal: 'center'
                }
            });
        }
    }, [enqueueSnackbar, onCreate, selectedEntity, successAction, t]);
    const handleOnUpdate = useCallback(async (values, primaryKeyValues) => {
        if (selectedEntity && (selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.unityBaseUpdateMethod)) {
            const entityName = selectedEntity === null || selectedEntity === void 0 ? void 0 : selectedEntity.entityName;
            if (selectedEntity.unityBaseUpdateMethod) {
                // Get primary key value object using path parameters and merge with data
                const pathObject = getPathObject(selectedEntity.unityBaseUpdateMethod.pathParameters, primaryKeyValues);
                const data = Object.assign(Object.assign({}, pathObject), { requestBody: values });
                const response = await onUpdate({ data }).catch((res) => {
                    enqueueSnackbar(res.message, {
                        variant: 'error',
                        anchorOrigin: {
                            vertical: 'top',
                            horizontal: 'center'
                        }
                    });
                });
                if ((response === null || response === void 0 ? void 0 : response.status) === 200) {
                    enqueueSnackbar(entityName
                        ? t(`${entityName} has been updated`)
                        : t(`Entity has been updated`), {
                        anchorOrigin: {
                            vertical: 'top',
                            horizontal: 'center'
                        },
                        action: successAction
                    });
                    handleFetchEntityData();
                }
            }
        }
        else {
            enqueueSnackbar(t(`Unable to retrieve entity methods`), {
                variant: 'error',
                anchorOrigin: {
                    vertical: 'top',
                    horizontal: 'center'
                }
            });
        }
    }, [
        selectedEntity,
        onUpdate,
        enqueueSnackbar,
        t,
        successAction,
        handleFetchEntityData
    ]);
    const handleOnCloseSideSheet = useCallback(() => {
        if (additionalOnClose) {
            additionalOnClose();
        }
        handleOnClose();
    }, [additionalOnClose, handleOnClose]);
    // const primaryKeyValues = useMemo(
    //   () => getPrimaryKeyValues(entityAttributes, null),
    //   [entityAttributes]
    // );
    // @TODO: Need to add a check if a promoted method for specific Entity has a static page
    // linked to it. It can fall back to it if there is no actions page
    const content = useMemo(() => {
        var _a, _b;
        if (page) {
            return (React.createElement(DndProvider, { backend: HTML5Backend }, React.createElement(PageContainer, { user: user, key: action === null || action === void 0 ? void 0 : action.actionId, pageData: page, widgetParams: {
                    pageId: page === null || page === void 0 ? void 0 : page.pageId,
                    contentId: (_a = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _a === void 0 ? void 0 : _a.searchValue,
                    nodeObj: selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.nodeObj,
                    parentNodeObj: selectedNodeParent === null || selectedNodeParent === void 0 ? void 0 : selectedNodeParent.nodeObj,
                    inquiryParams: selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.inquiryParams,
                    refreshTree: refreshTree,
                    requiredFieldsMap: ((_b = action === null || action === void 0 ? void 0 : action.parameters) === null || _b === void 0 ? void 0 : _b.requiredFieldMapping) || {},
                    setSideSheetWidth: setWidth,
                    setSideSheetButtonLabel: setButtonLabel,
                    setSideSheetOnSubmit: setOnSubmit,
                    setSideSheetAdditionalOnClose: setAdditionalOnClose,
                    setSideSheetProps: setOtherSideSheetProps,
                    closeSideSheet: handleOnClose,
                    onCreate: onCreate,
                    onUpdate: onUpdate
                }, disableMargins: true })));
        }
        else {
            return (React.createElement(ActionForm, { key: action === null || action === void 0 ? void 0 : action.actionId, entityAttributes: entityAttributes, foreignKeyData: foreignKeyData, onCreate: handleOnCreate, closeSideSheet: handleOnClose, onUpdate: handleOnUpdate, crudTableEditionData: crudTableEditionData, crudTableFormData: crudTableFormData, udpFieldInfos: udpFieldInfos }));
        }
    }, [
        action,
        crudTableEditionData,
        crudTableFormData,
        entityAttributes,
        foreignKeyData,
        handleOnClose,
        handleOnCreate,
        handleOnUpdate,
        selectedNode,
        selectedNodeParent,
        refreshTree,
        user,
        page,
        onCreate,
        onUpdate,
        udpFieldInfos
    ]);
    const sideSheetTitle = useMemo(() => {
        var _a, _b;
        var _c;
        if ((_a = action === null || action === void 0 ? void 0 : action.parameters) === null || _a === void 0 ? void 0 : _a.pageDisplayName) {
            return action.parameters.pageDisplayName;
        }
        else if (page) {
            return page === null || page === void 0 ? void 0 : page.name;
        }
        else {
            return (((action === null || action === void 0 ? void 0 : action.actionTypeId) === NodeActionEnums.Create
                ? 'Add new '
                : 'Edit ') +
                ((_c = (_b = action === null || action === void 0 ? void 0 : action.parameters) === null || _b === void 0 ? void 0 : _b.entityName) !== null && _c !== void 0 ? _c : actionPanel === null || actionPanel === void 0 ? void 0 : actionPanel.entityName));
        }
    }, [action, actionPanel, page]);
    return (React.createElement(SideSheet, Object.assign({ open: open, title: t(sideSheetTitle), buttonLabel: t(buttonLabel), onSubmit: onSubmit, onClose: handleOnCloseSideSheet, width: width }, otherSideSheetProps), loadingContent || loadingPage ? (React.createElement(React.Fragment, null, skeleton.map((sk, index) => (React.createElement(React.Fragment, { key: index }, sk))), React.createElement(LayoutUnit, { unit: "md" }), React.createElement(Skeleton, { variant: "rect", className: classes.skeletonButton }))) : (content)));
};
ActionSideSheet.propTypes = {
    /**
     * User object
     */
    user: PropTypes.object,
    /**
     * boolean to open/close sidesheet
     */
    open: PropTypes.bool,
    /**
     * dispatch function
     */
    dispatch: PropTypes.func,
    /**
     * selected action object
     */
    action: PropTypes.object,
    /**
     * action panels array
     */
    actionPanels: PropTypes.array,
    /**
     * catalog object
     */
    catalog: PropTypes.object,
    /**
     * Selected node object
     */
    selectedNodeObj: PropTypes.object
};
//# sourceMappingURL=ActionSideSheet.js.map