// (C) 2022-2026 GoodData Corporation
import { call, select } from "redux-saga/effects";
import { areObjRefsEqual, serializeObjRef, } from "@gooddata/sdk-model";
import { invalidQueryArguments } from "../events/general.js";
import { createCachedQueryService } from "../store/_infra/queryService.js";
import { selectCatalogAttributes } from "../store/catalog/catalogSelectors.js";
import { selectPreloadedAttributesWithReferences } from "../store/tabs/filterContext/filterContextSelectors.js";
export const QueryAttributeByDisplayFormService = createCachedQueryService("GDC.DASH/QUERY.DISPLAY.FORM.ATTRIBUTE", queryService, (query) => {
    const { payload: { displayForms }, } = query;
    return displayForms.map((df) => serializeObjRef(df)).join();
});
/**
 * Loads the attribute metadata for given display form. Primarily the metadata are loaded
 * from the preloaded filter attributes or catalog attributes. If the required attribute is not listed in the preloaded attributes or catalog
 * (e.g. deprecated attributes), the attribute metadata are fetched from the backend.
 */
async function loadAttributeByDisplayForm(ctx, catalogAttributes, displayFormRef, preloadedAttributesWithReferences) {
    const { backend, workspace } = ctx;
    // First try to get the attribute from preloaded filters
    let attribute = preloadedAttributesWithReferences?.find((attr) => attr.attribute.displayForms.some((df) => areObjRefsEqual(df.ref, displayFormRef)))?.attribute;
    if (!attribute) {
        // If the attribute is not in preloaded filters, try to get it from catalog attributes
        attribute = catalogAttributes.find((catalogAttribute) => catalogAttribute.displayForms.some((df) => areObjRefsEqual(df.ref, displayFormRef)))?.attribute;
    }
    if (attribute) {
        return attribute;
    }
    // If attribute is not in preloaded filters or catalog attributes, fetch it from backend
    return backend.workspace(workspace).attributes().getAttributeByDisplayForm(displayFormRef);
}
async function loadAttributes(ctx, catalogAttributes, displayForms, preloadedAttributesWithReferences) {
    return Promise.all(displayForms.map((df) => loadAttributeByDisplayForm(ctx, catalogAttributes, df, preloadedAttributesWithReferences)));
}
function* queryService(ctx, query) {
    const { payload: { displayForms }, correlationId, } = query;
    const preloadedAttributesWithReferences = yield select(selectPreloadedAttributesWithReferences);
    const catalogAttributes = yield select(selectCatalogAttributes);
    const attributes = yield call(loadAttributes, ctx, catalogAttributes, displayForms, preloadedAttributesWithReferences);
    if (!attributes) {
        throw invalidQueryArguments(ctx, `Cannot find attribute for given displayForm`, correlationId);
    }
    return attributes;
}
