import React, { useEffect, useState, useCallback, useMemo } from 'react';
import { apiMutate, useAxiosMutate } from '../../../../utilities';
import { getSanitizedName } from '../../../../utilities/entities/entityUtilities';
import { Form, FormSpy } from '../../../../utilities/form';
import { CardinalityTypeEnums, TransactionUiActionTypeEnums } from '../../../../enums';
import DetailsFormFields from './DynamicTransactionDomainFormFields';
import { AmbientCard } from '../../../../UI/surfaces/cards/AmbientCard';
import { LinearProgress } from '@material-ui/core';
import { useHandleAxiosSnackbar } from '../../../../utilities/apiHelpers';
import { useTranslation } from 'react-i18next';
import { ConfigService } from '../../../../configService';
const DynamicTransactionDomainForm = (props) => {
    var _a;
    const { transaction, formRef, domainName, transactionTypeId, transactionUiActionType, setHasUnsavedChanges, onSubmitSuccess, refetchTransaction, catalogObject } = props;
    const [entityAttributes, setEntityAttributes] = useState(null);
    const fullyQualifiedName = (_a = transaction === null || transaction === void 0 ? void 0 : transaction.entityBusinessKey) === null || _a === void 0 ? void 0 : _a.split('|')[0];
    const { handleErrorSnackbar, handleSuccessSnackbar } = useHandleAxiosSnackbar();
    const { t } = useTranslation();
    const [{ data: udpObjectInfo }, fetchUdpObjectInfo] = useAxiosMutate(ConfigService.productV1ApiUrl, `UdpObjectInfo/search`, {
        method: 'post',
        data: {
            eagerLoad: true,
            pageNumber: 1,
            pageSize: 50,
            filterElements: [
                {
                    searchField: 'sanitizedName',
                    searchOperator: '=',
                    searchValue: fullyQualifiedName
                        ? getSanitizedName(fullyQualifiedName)
                        : domainName
                }
            ]
        }
    });
    const updateFieldInfo = (tableEntries, catalogObjectFieldInfo, fkFieldInfo, fkDomainName) => {
        let updatedFields = {
            type: 'array',
            options: tableEntries,
            domainName: fkDomainName
        };
        const updatedFieldInfo = Object.assign(Object.assign({}, fkFieldInfo), updatedFields);
        const index = catalogObjectFieldInfo.findIndex((f) => f.name.toLowerCase() === fkFieldInfo.name.toLowerCase());
        if (index != -1) {
            catalogObjectFieldInfo[index] = updatedFieldInfo;
        }
    };
    const mergeCatalogObjectInfoFieldInfo = useCallback((entityCatalogObjectInfo, filteredEntityFieldInfo) => {
        let catalogObjectFieldInfoCombo = entityCatalogObjectInfo.map((entityCatalogObject) => {
            let matchingEntityFieldInfo = filteredEntityFieldInfo.find((fieldInfo) => {
                let formattedFieldName = fieldInfo.name.slice(0, 1).toLowerCase() +
                    fieldInfo.name.slice(1);
                if (fieldInfo.name == 'ID') {
                    formattedFieldName = formattedFieldName.toLowerCase();
                }
                return formattedFieldName == entityCatalogObject.name;
            });
            if (matchingEntityFieldInfo) {
                let additional_fields = {
                    hidden: matchingEntityFieldInfo.properties.maintainenceConfig.hidden,
                    associationLabel: matchingEntityFieldInfo.properties.maintainenceConfig
                        .associationLabel,
                    isPrimaryKey: matchingEntityFieldInfo.isPrimaryKey
                };
                return Object.assign(Object.assign({}, entityCatalogObject), additional_fields);
            }
            else {
                return entityCatalogObject;
            }
        });
        return catalogObjectFieldInfoCombo;
    }, []);
    const filterOutManyToManyRelationships = (CatalogObjectInfo) => {
        let entityCatalogObjectInfo = CatalogObjectInfo.filter((catalogObject) => {
            var _a, _b;
            const cardinality = (_b = (_a = catalogObject.extendedProperties) === null || _a === void 0 ? void 0 : _a.childEntityAssoc) === null || _b === void 0 ? void 0 : _b.Cardinality;
            if (cardinality != undefined) {
                return (cardinality != CardinalityTypeEnums.Many_To_Many &&
                    cardinality != CardinalityTypeEnums.One_To_One &&
                    catalogObject.name.toLowerCase() != 'businessobjectkey');
            }
            else {
                return catalogObject.name.toLowerCase() != 'businessobjectkey';
            }
        });
        return entityCatalogObjectInfo;
    };
    const updateFkFields = useCallback(async (entityCatalogObjectInfo, catalogObjectInfo) => {
        const childEntityAssociation = catalogObjectInfo.extendedProperties.childEntityAssoc;
        const cardinality = childEntityAssociation.Cardinality;
        if (cardinality != undefined) {
            const foreignKeyAssociationFields = childEntityAssociation.Keys[0].split(',');
            let fieldsInAssociationToIgnore = [
                'id',
                'businessobjectkey',
                'entitybusinesskey'
            ];
            return Promise.all(foreignKeyAssociationFields.map(async (fkFieldName) => {
                if (fkFieldName.toLowerCase() != 'id' &&
                    !fieldsInAssociationToIgnore.includes(fkFieldName.toLowerCase())) {
                    let fkFieldInfo = entityCatalogObjectInfo.find((field) => field.name.toLowerCase() == fkFieldName.toLowerCase());
                    const fkDomainName = getSanitizedName(childEntityAssociation.TargetType);
                    try {
                        const getTableEntriesResp = await apiMutate(ConfigService.productV1ApiUrl, `${fkDomainName}`, { method: 'get' });
                        if (getTableEntriesResp.data.length > 0 && fkFieldInfo) {
                            updateFieldInfo(getTableEntriesResp.data, entityCatalogObjectInfo, fkFieldInfo, fkDomainName);
                        }
                    }
                    catch (error) {
                        handleErrorSnackbar(new Error(t(`Error finiding field information! Please try again.`)));
                    }
                }
            }));
        }
    }, [handleErrorSnackbar, t]);
    const filterAdjustEntityAttributes = useCallback(async (catalogObjectInfo) => {
        let entityCatalogObjectInfo = catalogObjectInfo;
        entityCatalogObjectInfo = filterOutManyToManyRelationships(entityCatalogObjectInfo);
        const entityObjectInfoResponse = await fetchUdpObjectInfo();
        const entityObjectInfo = entityObjectInfoResponse.data.pageList[0];
        let filteredEntityFieldInfo = entityObjectInfo.objectFieldInfo.filter((fieldInfo) => fieldInfo.properties.isDefaultVisible);
        await Promise.all(entityCatalogObjectInfo.map((catalogObjectInfo) => {
            return updateFkFields(entityCatalogObjectInfo, catalogObjectInfo);
        }));
        entityCatalogObjectInfo = entityCatalogObjectInfo.filter((catalogObject) => !catalogObject.extendedProperties.childEntity);
        let mergedFieldInfo = mergeCatalogObjectInfoFieldInfo(entityCatalogObjectInfo, filteredEntityFieldInfo);
        return mergedFieldInfo;
    }, [fetchUdpObjectInfo, mergeCatalogObjectInfoFieldInfo, updateFkFields]);
    useEffect(() => {
        if (catalogObject) {
            filterAdjustEntityAttributes(catalogObject.properties).then((filteredResp) => {
                setEntityAttributes(filteredResp);
            });
        }
    }, [filterAdjustEntityAttributes, catalogObject]);
    const executeSaveChanges = useCallback(async (data) => apiMutate(ConfigService.productV1ApiUrl, `udpTransaction/${transaction === null || transaction === void 0 ? void 0 : transaction.transactionId}/saveChanges`, {
        method: 'put'
    }, data), [transaction === null || transaction === void 0 ? void 0 : transaction.transactionId]);
    const executeCreateTransactionAndDomain = useCallback(async (data) => apiMutate(ConfigService.productV1ApiUrl, `udpTransaction/transactionType/${transactionTypeId}/create`, {
        method: 'post'
    }, data), [transactionTypeId]);
    const onSubmit = useCallback(async (values) => {
        var _a, _b;
        try {
            const request = { data: values };
            let response = null;
            let successMessageAction = '';
            let errorMessageAction = '';
            if (transactionUiActionType ==
                TransactionUiActionTypeEnums.Render_Transaction_Details_Page) {
                response = await executeSaveChanges({ data: values });
                successMessageAction = 'saved';
                errorMessageAction = 'saving';
            }
            else if (transactionUiActionType ==
                TransactionUiActionTypeEnums.Render_Create_Transaction_Page) {
                response = await executeCreateTransactionAndDomain(request);
                successMessageAction = 'created';
                errorMessageAction = 'creating';
            }
            const { status, data } = response || {};
            const apiResult = data === null || data === void 0 ? void 0 : data.actionApiResult;
            if (status === 200) {
                // Success condition: No actionApiResult OR actionApiResult says success is true
                const isSuccessful = !apiResult || apiResult.success;
                if (isSuccessful) {
                    handleSuccessSnackbar(t(`Transaction has been ${successMessageAction} successfully`));
                    onSubmitSuccess === null || onSubmitSuccess === void 0 ? void 0 : onSubmitSuccess(response);
                }
                else if (apiResult === null || apiResult === void 0 ? void 0 : apiResult.errorMessage) {
                    handleErrorSnackbar(new Error(apiResult.errorMessage));
                }
            }
            else {
                // Handle non-200 status codes
                const defaultError = t(`Error ${errorMessageAction} Transaction. Please try again later.`);
                handleErrorSnackbar(new Error(defaultError));
            }
        }
        catch (error) {
            handleErrorSnackbar(error);
        }
        finally {
            if (setHasUnsavedChanges) {
                (_b = (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.restart(values);
                setHasUnsavedChanges(false);
            }
            if (refetchTransaction) {
                refetchTransaction();
            }
        }
    }, [
        executeSaveChanges,
        executeCreateTransactionAndDomain,
        handleSuccessSnackbar,
        handleErrorSnackbar,
        t,
        transactionUiActionType,
        setHasUnsavedChanges,
        formRef,
        onSubmitSuccess,
        refetchTransaction
    ]);
    const fieldAttributes = useMemo(() => {
        if (!entityAttributes) {
            return [];
        }
        return entityAttributes;
    }, [entityAttributes]);
    return fieldAttributes.length == 0 ? (React.createElement(LinearProgress, null)) : (React.createElement(AmbientCard, { fullWidth: true }, React.createElement(Form, { onSubmit: onSubmit, ref: formRef }, React.createElement(FormSpy, { subscription: { dirty: true } }, ({ dirty }) => {
        if (setHasUnsavedChanges) {
            setHasUnsavedChanges(dirty);
        }
    }), React.createElement(DetailsFormFields, { transaction: transaction, fieldAttributes: fieldAttributes, transactionTypeId: transactionTypeId }))));
};
export default DynamicTransactionDomainForm;
//# sourceMappingURL=DynamicTransactionDomainForm.js.map