import React, { useCallback, useEffect, useState } from 'react';
import { makeStyles, LinearProgress } from '@material-ui/core';
import { getSearchObject, getSearchIdentifiers } from '../../utilities/search/SearchUtilities';
import { AmbientCard } from '../../UI/surfaces/cards/AmbientCard';
import { InquirySearchTable } from './InquirySearchTable';
import clsx from 'clsx';
import { LogicalSearchOperatorEnums } from '../../enums/unitySystemEnums.ts';
import { useSearchFilterParamsMap } from '../../hooks/useSearchFilterParamsMap';
import { getSanitizedName } from '../../utilities/entities/entityUtilities';
const useStyles = makeStyles((theme) => ({
    root: {
        overflowX: 'auto'
    },
    searchCard: {
        paddingBottom: theme.spacing(2)
    },
    emptyStateWrapper: {
        display: 'flex',
        justifyContent: 'center',
        paddingTop: '25vh'
    }
}));
export const InquirySearchContainer = (props) => {
    const { advancedSearchItems, catalogObjects, classes: classProps, executeQueryAdHoc, isAdvancedSearch, loadSingleNode, onRowDoubleClick, searchItems, setSelectedSearchRows, apiMethodInstanceId } = props;
    const { root } = classProps || {};
    const classes = useStyles();
    const [searchList, setSearchList] = useState(null);
    const [loading, setLoading] = useState(false);
    const { getQueryFilterElements, getQueryFilterGroups, getQuerySearchOperator } = useSearchFilterParamsMap();
    const getQueryColumnsData = useCallback((apiMethodInstance) => {
        if (!apiMethodInstance)
            return [];
        let catalogMods = [];
        try {
            const catalogModificationStr = apiMethodInstance.catalogModification;
            const catalogModification = JSON.parse(catalogModificationStr);
            catalogMods = catalogModification;
        }
        catch (_a) {
            console.warn('Error parsing apiMethodInstance catalogModification');
        }
        return catalogMods;
    }, []);
    useEffect(() => {
        if (!catalogObjects) {
            setLoading(true);
        }
        if (!searchItems || !(catalogObjects === null || catalogObjects === void 0 ? void 0 : catalogObjects.length))
            return;
        setLoading(true);
        const promises = [];
        let list = [];
        const promiseIndexMap = {};
        const itemsList = !isAdvancedSearch
            ? searchItems
            : advancedSearchItems || [];
        itemsList.forEach((item, index) => {
            var _a;
            //Get filter elements, filter groups, and operator from query
            let filterElementsFromQuery = getQueryFilterElements(item.apiMethodInstance); //will this handle groups? if there is group within data builder
            let filterGroups = getQueryFilterGroups(item.apiMethodInstance);
            const logicalOperatorFromQuery = getQuerySearchOperator(item.apiMethodInstance);
            // Assigning queryColumnsData object here to know which columns are hidden based on
            // data browser query
            item.queryColumnsData = getQueryColumnsData(item.apiMethodInstance);
            //create new outer filter group to contain all filters in data builder query
            let outerQueryGroupId = 0;
            let queryOuterGroup = null;
            if (!!filterElementsFromQuery.length) {
                outerQueryGroupId = filterGroups.length + 1;
                queryOuterGroup = {
                    groupId: outerQueryGroupId,
                    logicalSearchOperator: logicalOperatorFromQuery
                };
            }
            //create new outer filter group to contain all filters from tree builder
            let outerTreeBuilderGroupId = 0;
            let inquiryOuterGroup = null;
            if (!!((_a = item === null || item === void 0 ? void 0 : item.searchFilterElements) === null || _a === void 0 ? void 0 : _a.length)) {
                outerTreeBuilderGroupId = outerQueryGroupId + 1;
                inquiryOuterGroup = {
                    groupId: outerTreeBuilderGroupId,
                    logicalSearchOperator: isAdvancedSearch
                        ? LogicalSearchOperatorEnums.And
                        : LogicalSearchOperatorEnums.Or
                };
            }
            //make the new outer query group the parent of non parent query groups (top level groups)
            filterGroups = filterGroups.map((group) => {
                if (!group.parentGroupId) {
                    group.parentGroupId = outerQueryGroupId;
                }
                return group;
            });
            //make the new outer group the group of filter elements with no group (top level filter elements)
            filterElementsFromQuery = filterElementsFromQuery.map((element) => {
                if (!element.groupId) {
                    element.groupId = outerQueryGroupId;
                }
                return element;
            });
            //add outer tree builder group Id to all tree builder filter elements
            item.searchFilterElements = item.searchFilterElements.map((element) => {
                element.groupId = outerTreeBuilderGroupId;
                return element;
            });
            //combine data builder query filters and tree builder filters
            const searchFilterElements = filterElementsFromQuery.concat(item.searchFilterElements || []);
            // Reassigning searchFilterElements to use the data browser filter elements
            // and the searched one
            item.searchFilterElements = searchFilterElements;
            //add new outer filter groups to filter group array
            if (!!inquiryOuterGroup) {
                filterGroups.push(inquiryOuterGroup);
            }
            if (!!queryOuterGroup) {
                filterGroups.push(queryOuterGroup);
            }
            item.searchFilterGroups = filterGroups;
            const searchObject = getSearchObject(searchFilterElements, 1, null, false, LogicalSearchOperatorEnums.And, filterGroups);
            let shouldSearch = true;
            if (!searchFilterElements.some((sfe) => sfe.searchOperator !== '=')) {
                const equalsSearchFilterElements = searchFilterElements.filter((sfe) => sfe.searchOperator === '=');
                if (!!equalsSearchFilterElements.length) {
                    const catalogObject = catalogObjects.find((co) => co.catalogObjectName === item.catalogReturnObject);
                    const coProperties = (catalogObject === null || catalogObject === void 0 ? void 0 : catalogObject.properties) || [];
                    if (!!coProperties.length) {
                        equalsSearchFilterElements.forEach((esfe) => {
                            if (!shouldSearch) {
                                return;
                            }
                            const matchingProperty = coProperties.find((cop) => {
                                var _a, _b;
                                return ((_a = cop.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === ((_b = esfe.searchField) === null || _b === void 0 ? void 0 : _b.toLowerCase());
                            });
                            if (matchingProperty === null || matchingProperty === void 0 ? void 0 : matchingProperty.type) {
                                let compareNumber = true;
                                let parsedValue = esfe.searchValue;
                                switch (matchingProperty.type) {
                                    case 'int':
                                        const intRegex = /[^0-9]/;
                                        if (intRegex.test(esfe.searchValue)) {
                                            parsedValue = NaN;
                                        }
                                        else {
                                            parsedValue = parseInt(esfe.searchValue);
                                        }
                                        break;
                                    case 'double':
                                    case 'decimal':
                                    case 'float':
                                        const floatRegex = /[^0-9.]/;
                                        if (floatRegex.test(esfe.searchValue)) {
                                            parsedValue = NaN;
                                        }
                                        else {
                                            parsedValue = parseFloat(esfe.searchValue);
                                        }
                                        break;
                                    // Add additional handling for different types below
                                    default:
                                        compareNumber = false;
                                        break;
                                }
                                if (compareNumber && isNaN(parsedValue)) {
                                    shouldSearch = false;
                                }
                            }
                        });
                    }
                }
            }
            if (shouldSearch && executeQueryAdHoc) {
                const data = { data: searchObject };
                promiseIndexMap[promises.length] = index;
                promises.push(executeQueryAdHoc(data, item.apiMethodId));
            }
            list.push({ queryData: null, searchItem: item });
        });
        Promise.all(promises.map((p) => p.catch((e) => e))).then((responses) => {
            var _a;
            responses.forEach((response, i) => {
                var _a;
                const index = promiseIndexMap[i];
                if (response.status === 200) {
                    const querySearchObj = list[index];
                    querySearchObj.queryData = response.data;
                }
                else if (!response.status) {
                    // handle response error
                    const querySearchObj = list[index];
                    console.error(`Retrieval Error Occured for ${(_a = querySearchObj === null || querySearchObj === void 0 ? void 0 : querySearchObj.searchItem) === null || _a === void 0 ? void 0 : _a.catalogReturnObject}`);
                }
            });
            let matchingItem = list.find((item) => {
                var _a, _b, _c, _d;
                return ((_b = (_a = item === null || item === void 0 ? void 0 : item.searchItem) === null || _a === void 0 ? void 0 : _a.apiMethodInstance) === null || _b === void 0 ? void 0 : _b.apiMethodInstanceId) ===
                    apiMethodInstanceId && ((_d = (_c = item === null || item === void 0 ? void 0 : item.queryData) === null || _c === void 0 ? void 0 : _c.pageList) === null || _d === void 0 ? void 0 : _d.length) === 1;
            });
            // Fallback to first item with single entry
            if (!matchingItem) {
                matchingItem = list.find((item) => {
                    var _a, _b;
                    return ((_b = (_a = item === null || item === void 0 ? void 0 : item.queryData) === null || _a === void 0 ? void 0 : _a.pageList) === null || _b === void 0 ? void 0 : _b.length) === 1;
                });
            }
            if (matchingItem) {
                const querySearchObj = matchingItem;
                const node = {};
                const searchItem = querySearchObj === null || querySearchObj === void 0 ? void 0 : querySearchObj.searchItem;
                const identifiers = getSearchIdentifiers(catalogObjects, searchItem.catalogReturnObject) || [];
                node[searchItem.catalogReturnObject] = {
                    rows: (_a = matchingItem === null || matchingItem === void 0 ? void 0 : matchingItem.queryData) === null || _a === void 0 ? void 0 : _a.pageList,
                    apiMethodId: searchItem.apiMethodId,
                    searchIdentifier: identifiers.toString(),
                    treeStructure: searchItem.treeStructure
                };
                loadSingleNode(node);
            }
            setSearchList(list);
            setLoading(false);
        });
    }, [
        searchItems,
        isAdvancedSearch,
        advancedSearchItems,
        loadSingleNode,
        catalogObjects,
        executeQueryAdHoc,
        getQueryFilterElements,
        getQueryColumnsData,
        getQueryFilterGroups,
        getQuerySearchOperator,
        apiMethodInstanceId
    ]);
    return (React.createElement("div", { className: clsx(classes.root, root) }, loading && React.createElement(LinearProgress, null), searchList === null || searchList === void 0 ? void 0 : searchList.map((searchObj) => {
        var _a, _b, _c, _d, _e, _f, _g;
        return (React.createElement("div", { key: searchObj.searchItem.catalogReturnObject, className: classes.searchCard }, React.createElement(AmbientCard, { key: `${searchObj.searchItem.catalogReturnObject}-${(_a = searchObj === null || searchObj === void 0 ? void 0 : searchObj.queryData) === null || _a === void 0 ? void 0 : _a.total}`, title: `${getSanitizedName(searchObj.searchItem.catalogReturnObject)} - ${searchObj.error
                ? searchObj.error
                : ((_b = searchObj === null || searchObj === void 0 ? void 0 : searchObj.queryData) === null || _b === void 0 ? void 0 : _b.total) || '0'}`, moreMessage: "Top 10 results...", moreButton: "Load More", moreButtonExpanded: "Minimize", more: !!((_d = (_c = searchObj === null || searchObj === void 0 ? void 0 : searchObj.queryData) === null || _c === void 0 ? void 0 : _c.pageList) === null || _d === void 0 ? void 0 : _d.length), header: true, fullWidth: true, globalToggle: true, collapseChildrenWhenExpanded: true, toggleGlobalExpanded: !!((_e = searchObj === null || searchObj === void 0 ? void 0 : searchObj.queryData) === null || _e === void 0 ? void 0 : _e.total), extendedList: React.createElement(InquirySearchTable, { key: searchObj.searchItem.id, queryData: searchObj.queryData || [], columns: searchObj.searchItem.columns, apiMethodId: searchObj.searchItem.apiMethodId, searchFilterElements: searchObj.searchItem.searchFilterElements, searchFilterGroups: searchObj.searchItem.searchFilterGroups, catalogReturnObject: searchObj.searchItem.catalogReturnObject, setSelectedSearchRows: setSelectedSearchRows, catalogObjects: catalogObjects, treeStructure: searchObj.searchItem.treeStructure, associatedInquiryTree: searchObj.searchItem.associatedInquiryTree || null, onRowDoubleClick: onRowDoubleClick, isAdvancedSearch: isAdvancedSearch, executeQuery: executeQueryAdHoc, queryColumnsData: searchObj.searchItem.queryColumnsData }) }, !!((_g = (_f = searchObj === null || searchObj === void 0 ? void 0 : searchObj.queryData) === null || _f === void 0 ? void 0 : _f.pageList) === null || _g === void 0 ? void 0 : _g.length) && (React.createElement(InquirySearchTable, { key: searchObj.searchItem.id, queryData: searchObj.queryData || [], columns: searchObj.searchItem.columns, apiMethodId: searchObj.searchItem.apiMethodId, searchFilterElements: searchObj.searchItem.searchFilterElements, searchFilterGroups: searchObj.searchItem.searchFilterGroups, catalogReturnObject: searchObj.searchItem.catalogReturnObject, setSelectedSearchRows: setSelectedSearchRows, catalogObjects: catalogObjects, treeStructure: searchObj.searchItem.treeStructure, associatedInquiryTree: searchObj.searchItem.associatedInquiryTree || null, onRowDoubleClick: onRowDoubleClick, topResultsOnly: true, topResultsSize: 10, isAdvancedSearch: isAdvancedSearch, executeQuery: executeQueryAdHoc, queryColumnsData: searchObj.searchItem.queryColumnsData })))));
    })));
};
//# sourceMappingURL=InquirySearchContainer.js.map