var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
import { useCallback, useEffect, useMemo, useState } from 'react';
import { ActivityFilter, collectAllTransitiveEntitiesUris, getEntitiesMapForTransitiveMatches, getDataTenantMatchGroups, getMatchesForDataTenantEntity, getMatchesFromDataTenants, getTransitiveMatches, isDataTenantEntity, isTempUri, withDtssPotentialItems, addGlobalFilterToQuery, addGetTransitiveMatchesMaskingOptions } from '@reltio/mdm-sdk';
import { usePagingSimulator } from '../usePagingSimulator';
import { useSafePromise } from '../useSafePromise';
import { useMdmDataTenantsWithIdBuilder, useMdmDtssPath, useMdmGlobalSearchRequestOptions, useMdmMetadata, useMdmTenant, useMdmShowMasking } from '../../contexts/MdmModuleContext';
var matchRuleLabelsCache = new Map();
// Match rule labels are static per (dtssPath, customerTenant), so the request is
// cached and reused across reloads (paging, filtering, sorting) instead of being
// refetched every time matches are loaded. Failed requests are evicted so a later
// load can retry.
var getCachedDataTenantMatchRuleLabels = function (dtssPath, customerTenant) {
    var cacheKey = "".concat(dtssPath, "::").concat(customerTenant);
    var cachedRequest = matchRuleLabelsCache.get(cacheKey);
    if (cachedRequest !== undefined) {
        return cachedRequest;
    }
    var request = getDataTenantMatchGroups({ dtssPath: dtssPath, customerTenant: customerTenant }).catch(function () {
        matchRuleLabelsCache.delete(cacheKey);
        return {};
    });
    matchRuleLabelsCache.set(cacheKey, request);
    return request;
};
var addDataTenantMatchRuleLabels = function (matches, entity, matchRuleLabels) {
    if (!Object.keys(matchRuleLabels).length) {
        return matches;
    }
    return matches.map(function (match) {
        var _a;
        return (isDataTenantEntity(entity) || isDataTenantEntity(match.object)) &&
            ((_a = match.matchRules) === null || _a === void 0 ? void 0 : _a.some(function (matchRuleUri) { return matchRuleLabels[matchRuleUri]; }))
            ? __assign(__assign({}, match), { matchRuleLabels: matchRuleLabels }) : match;
    });
};
export var useMatchesLoader = function (_a) {
    var enabled = _a.enabled, entity = _a.entity, filter = _a.filter, rules = _a.rules, onFinishLoading = _a.onFinishLoading, onStartLoading = _a.onStartLoading, options = _a.options, page = _a.page, rowsPerPage = _a.rowsPerPage, sorting = _a.sorting, markMatchedValues = _a.markMatchedValues;
    var _b = sorting || {}, order = _b.order, field = _b.field;
    var _c = useState(0), total = _c[0], setTotal = _c[1];
    var _d = useState([]), matches = _d[0], setMatches = _d[1];
    var _e = useState({}), matchRuleLabels = _e[0], setMatchRuleLabels = _e[1];
    var _f = useState({}), entitiesMap = _f[0], setEntitiesMap = _f[1];
    var metadata = useMdmMetadata();
    var tenant = useMdmTenant();
    var dtssPath = useMdmDtssPath();
    var dataTenants = useMdmDataTenantsWithIdBuilder();
    var showMasking = useMdmShowMasking();
    var _g = useMdmGlobalSearchRequestOptions() || {}, activityFilter = _g.activityFilter, globalFilter = _g.globalFilter;
    var activeness = typeof options.showInactiveEntities === 'boolean'
        ? options.showInactiveEntities
            ? ActivityFilter.ALL
            : ActivityFilter.ACTIVE_ONLY
        : activityFilter;
    var entityUri = entity === null || entity === void 0 ? void 0 : entity.uri;
    var dtssParams = useMemo(function () { return ({
        dtssPath: dtssPath,
        dataTenants: dataTenants,
        entity: entity,
        customerTenant: tenant,
        dtssRequest: getMatchesFromDataTenants
    }); }, 
    //eslint-disable-next-line react-hooks/exhaustive-deps
    [dtssPath, dataTenants, entityUri, tenant]);
    //eslint-disable-next-line react-hooks/exhaustive-deps
    var getTransitiveMatchesWithDtss = useCallback(withDtssPotentialItems(dtssParams, getTransitiveMatches), [
        dtssParams
    ]);
    var getTransitiveMatchesWithPaging = usePagingSimulator(getTransitiveMatchesWithDtss);
    var getPagedMatchesForDataTenantEntity = usePagingSimulator(getMatchesForDataTenantEntity);
    var safePromise = useSafePromise();
    var safeMatchRuleLabelsPromise = useSafePromise();
    var getMatches = useCallback(function (force) {
        if (force === void 0) { force = false; }
        if (!enabled || isTempUri(entityUri)) {
            setTotal(0);
            setMatches([]);
            setEntitiesMap({});
            return;
        }
        onStartLoading === null || onStartLoading === void 0 ? void 0 : onStartLoading();
        var matchesRequest = isDataTenantEntity(entity)
            ? getPagedMatchesForDataTenantEntity({
                dtssPath: dtssPath,
                entity: entity,
                customerTenant: tenant,
                dataTenants: dataTenants,
                offset: page * rowsPerPage,
                max: rowsPerPage,
                force: force
            })
            : getTransitiveMatchesWithPaging(__assign(__assign({}, addGetTransitiveMatchesMaskingOptions(metadata, {
                entityUri: entityUri,
                max: rowsPerPage,
                filter: addGlobalFilterToQuery(globalFilter, filter) || '',
                rules: rules,
                sort: field,
                order: order,
                markMatchedValues: markMatchedValues,
                deep: options.showTransitiveMatches ? undefined : 1,
                activeness: activeness
            }, showMasking)), { offset: page * rowsPerPage, force: force }));
        safePromise(matchesRequest)
            .then(function (result) {
            var response = result.response, total = result.total, originalResponse = result.originalResponse;
            setTotal(total);
            var matchUris = collectAllTransitiveEntitiesUris(originalResponse);
            if (matchUris.length > 0) {
                setEntitiesMap(getEntitiesMapForTransitiveMatches(originalResponse));
            }
            setMatches(response);
        })
            .catch(function (error) {
            console.warn("Can't load entities or total for matches:", error);
            setMatches([]);
            setTotal(0);
        })
            .finally(function () {
            onFinishLoading === null || onFinishLoading === void 0 ? void 0 : onFinishLoading();
        });
    }, 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [
        globalFilter,
        activeness,
        dataTenants,
        dtssPath,
        enabled,
        entityUri,
        field,
        filter,
        rules,
        markMatchedValues,
        getPagedMatchesForDataTenantEntity,
        getTransitiveMatchesWithPaging,
        onFinishLoading,
        onStartLoading,
        options,
        order,
        page,
        rowsPerPage,
        safePromise,
        tenant,
        showMasking
    ]);
    useEffect(function () {
        getMatches();
    }, [getMatches]);
    // Match rule labels are loaded independently of the matches request so the
    // matches list renders without waiting for them; they are applied as a
    // derived layer once available. Keyed on a stable boolean rather than the
    // dataTenants array reference to avoid re-firing on every render.
    var hasDataTenants = !!(dataTenants === null || dataTenants === void 0 ? void 0 : dataTenants.length);
    useEffect(function () {
        if (!dtssPath || !tenant || !hasDataTenants) {
            setMatchRuleLabels({});
            return;
        }
        safeMatchRuleLabelsPromise(getCachedDataTenantMatchRuleLabels(dtssPath, tenant))
            .then(setMatchRuleLabels)
            .catch(function () { return setMatchRuleLabels({}); });
    }, [dtssPath, tenant, hasDataTenants, safeMatchRuleLabelsPromise]);
    var matchesWithRuleLabels = useMemo(function () { return addDataTenantMatchRuleLabels(matches, entity, matchRuleLabels); }, [matches, entity, matchRuleLabels]);
    var loadMatches = useCallback(function () {
        getMatches(true);
    }, [getMatches]);
    return {
        total: total,
        matches: matchesWithRuleLabels,
        entitiesMap: entitiesMap,
        loadMatches: loadMatches
    };
};
