import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { CkRichEditor } from '../UI/inputs/richEditors/CkRichEditor';
import { makeStyles, TextField, LinearProgress } from '@material-ui/core';
import { Field, Form } from '../utilities/form';
import { FluentTextFieldAutoComplete } from '../UI/inputs/textField/FluentTextFieldAutoComplete';
import { useTranslation } from 'react-i18next';
import { useActionState } from '../hooks/useActions';
import { constructBusinessObjectArrFromTree } from '../utilities/tree/TreeUtilities';
import { LayoutUnit } from '../layout/LayoutUnit';
import { UdpEnums } from '../enums/unitySystemEnums';
import { useHandleAxiosSnackbar } from '../utilities/apiHelpers';
import { useUser } from '../utilities/auth/useUser';
import { differenceWith } from 'lodash-es';
import { executeQueryAdHoc, getBaseMethod, executeQueryWithParameters } from '../udp/utilities/methodUtils';
import { ShortcutContentFinder } from '../udp/ShortcutContent/ShortcutContentFinder';
import { AmbientCard } from '../UI/surfaces/cards/AmbientCard';
import { useShellStore } from '../stores/shellStore';
import { FluentDatePicker } from '../UI/inputs/pickers/FluentDatePicker';
import { useActionStore } from '../stores/actionStore';
import { FILE_TO_TYPES } from '../constants/reminderConstants';
import { getSearchObject } from '../utilities/search/SearchUtilities';
const useStyles = makeStyles((theme) => {
    var _a;
    return ({
        root: {},
        editor: {
            '& .ck-editor__main > .ck-editor__editable_inline': {
                backgroundColor: ((_a = theme === null || theme === void 0 ? void 0 : theme.getThemeData()) === null || _a === void 0 ? void 0 : _a.mode) === 'dark'
                    ? theme.palette.grey[800]
                    : theme.palette.grey[100]
            }
        },
        row: {
            display: 'flex',
            justifyContent: 'space-between'
        },
        input: {
            height: 34,
            padding: 0
        },
        formTextInput: {
            fontSize: 14
        },
        labelRoot: {
            fontSize: 14
        }
    });
});
export const RemindersScreen = (props) => {
    const { formRef, onSubmit, shortcutContentFinderEnabled, id, viewOnly, reloadReminders } = props;
    const [reminder, setReminder] = useState('');
    const [typeOptions, setTypeOptions] = useState([]);
    const [templateOptions, setTemplateOptions] = useState([]);
    const [reminderId, setReminderId] = useState(id || '');
    const [existingReminderFiledFor, setExistingReminderFiledFor] = useState([]);
    const [existingReminderObj, setExistingReminderObj] = useState(null);
    const [loading, setLoading] = useState(false);
    const classes = useStyles(props);
    const { t } = useTranslation();
    const actionState = useActionState();
    const shellHidden = useShellStore((state) => state.shellHidden);
    const { menuListState, catalogPromotedEntities } = actionState;
    const { handleSuccessSnackbar, handleErrorSnackbar } = useHandleAxiosSnackbar();
    const user = useUser();
    const editorRef = useRef(null);
    const selectedNode = useActionStore((state) => state.selectedNode);
    const selectedMenu = useMemo(() => {
        if (menuListState.menuList.length) {
            return menuListState.menuList[menuListState.selectedMenuIndex] || null;
        }
        return null;
    }, [menuListState]);
    const reminderGetFullApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder, 'unityBaseGetFullMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const reminderTypeSearchApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder_Type, 'unityBaseSearchMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const reminderTemplateSearchApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder_Template, 'unityBaseSearchMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const createReminderApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder, 'unityBaseCreateMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const updateReminderApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder, 'unityBaseUpdateMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const createReminderFiledForApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder_Filed_For, 'unityBaseCreateMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const updateReminderFiledForApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder_Filed_For, 'unityBaseUpdateMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const deleteReminderFiledForApiMethod = useMemo(() => {
        return getBaseMethod(UdpEnums.Udp_Reminder_Filed_For, 'unityBaseDeleteMethod', catalogPromotedEntities);
    }, [catalogPromotedEntities]);
    const disabled = useMemo(() => {
        return viewOnly;
    }, [viewOnly]);
    const handleSaveReminder = useCallback(async (values) => {
        var _a, _b;
        let response = null;
        const reminderDate = new Date((_a = values === null || values === void 0 ? void 0 : values.reminderDate) === null || _a === void 0 ? void 0 : _a.setHours(0, 0, 0, 0));
        const data = {
            requestBody: {
                tenantId: user === null || user === void 0 ? void 0 : user.currentTenantId,
                typeCode: (_b = values === null || values === void 0 ? void 0 : values.type) === null || _b === void 0 ? void 0 : _b.code,
                subject: values === null || values === void 0 ? void 0 : values.subject,
                content: values === null || values === void 0 ? void 0 : values.reminder,
                unityUserId: user === null || user === void 0 ? void 0 : user.id,
                userDisplayName: `${user === null || user === void 0 ? void 0 : user.firstName} ${user === null || user === void 0 ? void 0 : user.familyName}`,
                reminderDate: reminderDate.toDateString()
            }
        };
        if (reminderId) {
            if (updateReminderApiMethod) {
                // Set the url parameter for updating reminder
                data['{iD}'] = reminderId;
                response = await executeQueryWithParameters({ data }, updateReminderApiMethod.apiMethodId).catch((e) => handleErrorSnackbar(e, 'Could not Update Reminder'));
            }
            else {
                handleErrorSnackbar(null, 'Update Reminder Method Not Promoted');
            }
        }
        else {
            if (createReminderApiMethod) {
                response = await executeQueryWithParameters({ data }, createReminderApiMethod.apiMethodId).catch((e) => handleErrorSnackbar(e, 'Could not Save Reminder'));
            }
            else {
                handleErrorSnackbar(null, 'Create Reminder Method Not Promoted');
            }
        }
        if ((response === null || response === void 0 ? void 0 : response.status) === 200) {
            if (!reminderId) {
                setReminderId(response.data.id || '');
                handleSuccessSnackbar('Reminder Saved');
            }
            else {
                handleSuccessSnackbar('Reminder Updated');
            }
            if (reloadReminders) {
                reloadReminders();
            }
            return response.data.id || reminderId;
        }
        return reminderId;
    }, [
        createReminderApiMethod,
        updateReminderApiMethod,
        reminderId,
        setReminderId,
        handleErrorSnackbar,
        handleSuccessSnackbar,
        user,
        reloadReminders
    ]);
    const reminderFiledForToComparator = (nftc1, nftc2) => {
        return (nftc1 === null || nftc1 === void 0 ? void 0 : nftc1.value) === (nftc2 === null || nftc2 === void 0 ? void 0 : nftc2.value);
    };
    const handleReminderFiledFor = useCallback(async (values, reminderdIdToFileFor) => {
        var _a;
        // Get the reminderFiledFor objects to delete
        const reminderFiledForToDelete = differenceWith(existingReminderFiledFor, values === null || values === void 0 ? void 0 : values.fileTo, reminderFiledForToComparator);
        // Get the reminderFiledFor objects to create
        const reminderFiledForToCreate = differenceWith(values === null || values === void 0 ? void 0 : values.fileTo, existingReminderFiledFor, reminderFiledForToComparator);
        if (reminderdIdToFileFor) {
            if (deleteReminderFiledForApiMethod) {
                const deletedPromises = [];
                reminderFiledForToDelete.forEach((nftd) => {
                    const data = {};
                    data['{reminderID}'] = reminderdIdToFileFor;
                    data['{entityBusinessKey}'] = nftd.value;
                    deletedPromises.push(executeQueryWithParameters({ data }, deleteReminderFiledForApiMethod.apiMethodId));
                });
                await Promise.all(deletedPromises.map((p) => p.catch((e) => e))).then((responses) => {
                    if (responses.length !== deletedPromises.length) {
                        console.warn(`Not all Reminder Filed For deleted`);
                    }
                });
            }
            else {
                handleErrorSnackbar(null, 'Delete Reminder Filed For Method Not Promoted');
            }
            if (createReminderFiledForApiMethod) {
                const createdPromises = [];
                reminderFiledForToCreate.forEach((nftc) => {
                    var _a;
                    const data = {
                        requestBody: {
                            reminderId: reminderdIdToFileFor,
                            entityBusinessKey: nftc.value,
                            domainObject: nftc.domainObject,
                            type: ((_a = values === null || values === void 0 ? void 0 : values.fileToType) === null || _a === void 0 ? void 0 : _a.value) || 1
                        }
                    };
                    createdPromises.push(executeQueryWithParameters({ data }, createReminderFiledForApiMethod.apiMethodId));
                });
                await Promise.all(createdPromises.map((p) => p.catch((e) => e))).then((responses) => {
                    responses.forEach((response) => {
                        if (response.status === 200) {
                            const entityBusinessKey = response.data.entityBusinessKey;
                            const matchingReminderFiledFor = reminderFiledForToCreate.find((nftc) => nftc.value === entityBusinessKey);
                            if (!matchingReminderFiledFor) {
                                console.warn(`Reminder Filed For not created for all file to entities`);
                            }
                        }
                    });
                });
                setExistingReminderFiledFor(values === null || values === void 0 ? void 0 : values.fileTo);
            }
            else {
                handleErrorSnackbar(null, 'Create Reminder Filed For Method Not Promoted');
            }
            if (updateReminderFiledForApiMethod) {
                const updatedPromises = [];
                (_a = values === null || values === void 0 ? void 0 : values.fileTo) === null || _a === void 0 ? void 0 : _a.forEach((nftu) => {
                    var _a;
                    const data = {
                        requestBody: {
                            reminderId: reminderdIdToFileFor,
                            entityBusinessKey: nftu.value,
                            domainObject: nftu.domainObject,
                            type: ((_a = values === null || values === void 0 ? void 0 : values.fileToType) === null || _a === void 0 ? void 0 : _a.value) || 1
                        }
                    };
                    data['{reminderID}'] = reminderdIdToFileFor;
                    data['{entityBusinessKey}'] = nftu.value;
                    updatedPromises.push(executeQueryWithParameters({ data }, updateReminderFiledForApiMethod.apiMethodId));
                });
                await Promise.all(updatedPromises.map((p) => p.catch((e) => e))).then((responses) => {
                    responses.forEach((response) => {
                        var _a;
                        if (response.status === 200) {
                            const entityBusinessKey = response.data.entityBusinessKey;
                            const matchingReminderFiledFor = (_a = values === null || values === void 0 ? void 0 : values.fileTo) === null || _a === void 0 ? void 0 : _a.find((nftu) => nftu.value === entityBusinessKey);
                            if (!matchingReminderFiledFor) {
                                console.warn(`Reminder Filed For not updated for all file to entities`);
                            }
                        }
                    });
                });
                setExistingReminderFiledFor(values === null || values === void 0 ? void 0 : values.fileTo);
            }
            else {
                handleErrorSnackbar(null, 'Update Reminder Filed For Method Not Promoted');
            }
        }
    }, [
        createReminderFiledForApiMethod,
        updateReminderFiledForApiMethod,
        deleteReminderFiledForApiMethod,
        handleErrorSnackbar,
        existingReminderFiledFor,
        setExistingReminderFiledFor
    ]);
    const handleOnSubmit = useCallback(async (values) => {
        if (onSubmit) {
            onSubmit(Object.assign({ reminder }, values));
        }
        else {
            const reminderdIdToFileFor = await handleSaveReminder(Object.assign({ reminder }, values));
            await handleReminderFiledFor(Object.assign({ reminder }, values), reminderdIdToFileFor);
        }
    }, [reminder, onSubmit, handleSaveReminder, handleReminderFiledFor]);
    const handleTextEditorChange = (reminder) => {
        setReminder(reminder);
    };
    const onTemplateChange = useCallback((value) => {
        var _a, _b, _c, _d, _e, _f;
        (_b = (_a = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.change('subject', (value === null || value === void 0 ? void 0 : value.subject) || '');
        const type = typeOptions.find((option) => option.code === value.typeCode);
        (_d = (_c = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _c === void 0 ? void 0 : _c.form) === null || _d === void 0 ? void 0 : _d.change('type', type || null);
        (_f = (_e = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _e === void 0 ? void 0 : _e.form) === null || _f === void 0 ? void 0 : _f.change('reminderDate', value.reminderDate === '0001-01-01T00:00:00'
            ? new Date()
            : new Date(value.reminderDate));
        setReminder((value === null || value === void 0 ? void 0 : value.content) || '');
    }, [setReminder, formRef, typeOptions]);
    const handleShortcutOnSelect = useCallback((shortcutContent) => {
        var _a, _b, _c;
        (_b = (_a = editorRef === null || editorRef === void 0 ? void 0 : editorRef.current) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.change((writer) => {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            const insertPosition = (_d = (_c = (_b = (_a = editorRef === null || editorRef === void 0 ? void 0 : editorRef.current) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.document) === null || _c === void 0 ? void 0 : _c.selection) === null || _d === void 0 ? void 0 : _d.getFirstPosition();
            writer.remove((_h = (_g = (_f = (_e = editorRef === null || editorRef === void 0 ? void 0 : editorRef.current) === null || _e === void 0 ? void 0 : _e.model) === null || _f === void 0 ? void 0 : _f.document) === null || _g === void 0 ? void 0 : _g.selection) === null || _h === void 0 ? void 0 : _h.getFirstRange());
            writer.insertText(shortcutContent, insertPosition);
        });
        setReminder((_c = editorRef === null || editorRef === void 0 ? void 0 : editorRef.current) === null || _c === void 0 ? void 0 : _c.getData());
    }, [editorRef, setReminder]);
    const fileToOptions = useMemo(() => {
        let options = [];
        if (selectedMenu) {
            options = constructBusinessObjectArrFromTree(selectedMenu);
        }
        return options;
    }, [selectedMenu]);
    useEffect(() => {
        // TODO: update to use getAll reminderTypes
        const getTypeOptions = async () => {
            var _a;
            let options = [];
            if (reminderTypeSearchApiMethod) {
                const filterElements = [];
                const searchObject = getSearchObject(filterElements, 1, 200, true);
                const data = { data: searchObject };
                const typesResponse = await executeQueryAdHoc(data, reminderTypeSearchApiMethod.apiMethodId);
                if ((typesResponse === null || typesResponse === void 0 ? void 0 : typesResponse.status) === 200) {
                    options = ((_a = typesResponse.data) === null || _a === void 0 ? void 0 : _a.pageList) || [];
                }
            }
            setTypeOptions(options);
        };
        getTypeOptions();
    }, [reminderTypeSearchApiMethod, setTypeOptions, user]);
    useEffect(() => {
        // TODO: update to use getAll reminderTemplates
        const getTemplateOptions = async () => {
            var _a;
            let options = [];
            if (reminderTemplateSearchApiMethod) {
                const filterElements = [];
                const searchObject = getSearchObject(filterElements, 1, 200, true);
                const data = { data: searchObject };
                const templatesResponse = await executeQueryAdHoc(data, reminderTemplateSearchApiMethod.apiMethodId);
                if ((templatesResponse === null || templatesResponse === void 0 ? void 0 : templatesResponse.status) === 200) {
                    options = ((_a = templatesResponse.data) === null || _a === void 0 ? void 0 : _a.pageList) || [];
                }
            }
            setTemplateOptions(options);
        };
        getTemplateOptions();
    }, [reminderTemplateSearchApiMethod, setTemplateOptions, user]);
    useEffect(() => {
        const getExistingReminder = async () => {
            let existingReminderObj = null;
            const data = {};
            if (reminderGetFullApiMethod) {
                setLoading(true);
                data['{iD}'] = id;
                const reminderResponse = await executeQueryWithParameters({ data }, reminderGetFullApiMethod.apiMethodId).catch((e) => {
                    console.error(e);
                    setLoading(false);
                });
                if ((reminderResponse === null || reminderResponse === void 0 ? void 0 : reminderResponse.status) === 200) {
                    existingReminderObj = reminderResponse.data;
                }
            }
            setExistingReminderObj(existingReminderObj);
            setReminder(existingReminderObj === null || existingReminderObj === void 0 ? void 0 : existingReminderObj.content);
            setLoading(false);
        };
        if (id) {
            getExistingReminder();
        }
    }, [id, reminderGetFullApiMethod]);
    useEffect(() => {
        var _a, _b;
        if (!existingReminderObj || !(fileToOptions === null || fileToOptions === void 0 ? void 0 : fileToOptions.length)) {
            return;
        }
        const initialFileTos = fileToOptions.filter((option) => {
            return existingReminderObj.reminderFiledFor.find((nff) => option.value === nff.entityBusinessKey);
        });
        setExistingReminderFiledFor(initialFileTos);
        (_b = (_a = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.change('fileTo', initialFileTos);
    }, [existingReminderObj, fileToOptions, formRef]);
    useEffect(() => {
        var _a, _b;
        if (!existingReminderObj || !(typeOptions === null || typeOptions === void 0 ? void 0 : typeOptions.length)) {
            return;
        }
        const initialType = typeOptions.find((option) => option.code === existingReminderObj.typeCode);
        (_b = (_a = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.change('type', initialType || null);
    }, [existingReminderObj, typeOptions, formRef]);
    useEffect(() => {
        var _a, _b;
        if (!existingReminderObj) {
            return;
        }
        (_b = (_a = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.change('subject', (existingReminderObj === null || existingReminderObj === void 0 ? void 0 : existingReminderObj.subject) || '');
    }, [existingReminderObj, formRef]);
    useEffect(() => {
        var _a, _b;
        if (!(existingReminderObj === null || existingReminderObj === void 0 ? void 0 : existingReminderObj.reminderDate)) {
            return;
        }
        (_b = (_a = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.change('reminderDate', new Date(existingReminderObj.reminderDate));
    }, [existingReminderObj, formRef]);
    useEffect(() => {
        var _a, _b, _c;
        if (!existingReminderObj) {
            return;
        }
        const matchingReminderFiledFor = (_a = existingReminderObj.reminderFiledFor) === null || _a === void 0 ? void 0 : _a.find((rff) => {
            var _a;
            return rff.domainObject === ((_a = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.properties) === null || _a === void 0 ? void 0 : _a.catalogReturnObject);
        });
        const initialFileToType = FILE_TO_TYPES.find((option) => option.value === (matchingReminderFiledFor === null || matchingReminderFiledFor === void 0 ? void 0 : matchingReminderFiledFor.type));
        (_c = (_b = formRef === null || formRef === void 0 ? void 0 : formRef.current) === null || _b === void 0 ? void 0 : _b.form) === null || _c === void 0 ? void 0 : _c.change('fileToType', initialFileToType || null);
    }, [existingReminderObj, typeOptions, formRef, selectedNode]);
    return (React.createElement("div", { className: classes.root }, loading && React.createElement(LinearProgress, { color: "secondary" }), React.createElement(AmbientCard, { fullWidth: true, header: true }, React.createElement(Form, { onSubmit: handleOnSubmit, ref: formRef }, React.createElement(Field, { component: FluentTextFieldAutoComplete, label: t('File To'), name: "fileTo", id: "fileTo", fullWidth: true, variant: "outlined", margin: "dense", size: "small", options: fileToOptions || [], optionKey: 'label', required: true, limitTags: !viewOnly ? 2 : -1, isMultiple: true, disabled: disabled }), React.createElement(Field, { component: FluentTextFieldAutoComplete, label: t('File To Type'), name: "fileToType", id: "fileToType", fullWidth: true, variant: "outlined", margin: "dense", size: "small", options: FILE_TO_TYPES || [], optionKey: 'label', required: true, disabled: disabled }), React.createElement("div", { className: classes.row }, React.createElement("div", { style: { width: '100%' } }, React.createElement(Field, { component: FluentTextFieldAutoComplete, label: t('Type'), name: "type", id: "type", fullWidth: true, variant: "outlined", margin: "dense", size: "small", options: typeOptions || [], optionKey: 'name', required: true, disabled: disabled })), !viewOnly && (React.createElement("div", { style: { width: '100%', marginLeft: 8 } }, React.createElement(Field, { component: FluentTextFieldAutoComplete, label: t('Template'), name: "template", id: "template", fullWidth: true, variant: "outlined", margin: "dense", size: "small", options: templateOptions || [], optionKey: 'name', additionalOnChangeAction: onTemplateChange })))), React.createElement(Field, { component: FluentDatePicker, label: t('Reminder Date'), name: "reminderDate", id: "reminderDate", fullWidth: true, variant: "outlined", size: "small", margin: "dense", required: true, disabled: disabled }), React.createElement(Field, { component: TextField, label: t('Subject'), name: "subject", id: "subject", fullWidth: true, variant: "outlined", size: "small", margin: "dense", required: true, disabled: disabled, InputProps: {
            classes: {
                root: classes === null || classes === void 0 ? void 0 : classes.input,
                input: classes === null || classes === void 0 ? void 0 : classes.formTextInput
            }
        }, InputLabelProps: {
            classes: {
                root: classes === null || classes === void 0 ? void 0 : classes.labelRoot
            }
        } }), React.createElement(LayoutUnit, { unit: "nudge" }), React.createElement(CkRichEditor, { handleChange: handleTextEditorChange, classes: { editor: classes.editor }, data: reminder, editorRef: editorRef, isUsingRef: true, readOnly: disabled }))), React.createElement(LayoutUnit, { unit: "nudge" }), shortcutContentFinderEnabled && (React.createElement(AmbientCard, { fullWidth: true, header: true, lastChildBottomPadding: '0px', cardContentHeight: `calc(100vh - ${shellHidden ? '568px' : '623px'})` }, React.createElement(ShortcutContentFinder, { onSelect: handleShortcutOnSelect })))));
};
//# sourceMappingURL=RemindersScreen.js.map