// (C) 2022-2026 GoodData Corporation
import { all, call, put, select } from "redux-saga/effects";
import { areObjRefsEqual, filterObjRef, idRef, isArbitraryAttributeFilter, isAttributeFilter, isDrillToCustomUrl, isMatchAttributeFilter, isNegativeAttributeFilter, widgetRef, } from "@gooddata/sdk-model";
import { dashboardAttributeFilterItemToAttributeFilter } from "../../../converters/filterConverters.js";
import { queryWidgetFilters } from "../../queries/widgets.js";
import { query } from "../../store/_infra/queryCall.js";
import { selectAllCatalogDisplayFormsMap } from "../../store/catalog/catalogSelectors.js";
import { selectDrillTargetsByWidgetRef } from "../../store/drillTargets/drillTargetsSelectors.js";
import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
import { selectFilterContextAttributeFilterItems } from "../../store/tabs/filterContext/filterContextSelectors.js";
import { uiActions } from "../../store/ui/index.js";
import { extractDashboardFilterDisplayFormIdentifiers, extractDisplayFormIdentifiers, extractInsightFilterDisplayFormIdentifiers, } from "../widgets/validation/insightDrillDefinitionUtils.js";
import { isDisplayFormRelevantToDrill } from "./isDisplayFormRelevantToDrill.js";
//
export function* validateDrillToCustomUrlParams(widgets) {
    const possibleInvalidDrills = yield all(widgets.map((widget) => call(validateWidgetDrillToCustomUrlParams, widget)));
    const invalidDrills = possibleInvalidDrills.filter(({ invalidDrills }) => invalidDrills.length > 0);
    if (invalidDrills.length === 0) {
        yield put(uiActions.resetInvalidCustomUrlDrillParameterWidget(widgets));
    }
    else {
        yield put(uiActions.setInvalidCustomUrlDrillParameterWidgets(invalidDrills));
    }
}
function* validateWidgetDrillToCustomUrlParams(widget) {
    const selectDrillTargetsByWidgetRefSelector = selectDrillTargetsByWidgetRef(widgetRef(widget));
    const drillTargets = yield select(selectDrillTargetsByWidgetRefSelector);
    if (!drillTargets?.availableDrillTargets) {
        // skip this part of the validation in case the drill targets are not available yet
        return {
            widget,
            invalidDrills: [],
        };
    }
    const displayForms = yield select(selectAllCatalogDisplayFormsMap);
    const widgetFilters = yield call(query, queryWidgetFilters(widget.ref));
    const widgetAttributeFilters = widgetFilters.filter(isAttributeFilter);
    const sanitizedWidgetAttributeFilters = widgetAttributeFilters.map((filter) => sanitizeAttributeFilter(filter, displayForms));
    const dashboardFilters = yield select(selectFilterContextAttributeFilterItems);
    const dashboardAttributeFilters = dashboardFilters.map(dashboardAttributeFilterItemToAttributeFilter);
    const sanitizedDashboardAttributeFilters = dashboardAttributeFilters.map((filter) => sanitizeAttributeFilter(filter, displayForms));
    const attributeFilterConfigs = yield select(selectAttributeFilterConfigsOverrides);
    return widget.drills.filter(isDrillToCustomUrl).reduce((acc, drillDefinition) => {
        const ids = extractDisplayFormIdentifiers([drillDefinition]);
        const hasInvalidParam = ids.some((identifier) => {
            const displayForm = displayForms.get(identifier);
            if (!displayForm) {
                // the drill as a whole is invalid, no reason to validate the parameters
                return false;
            }
            return !isDisplayFormRelevantToDrill(drillDefinition, drillTargets.availableDrillTargets, displayForm);
        });
        const dashboardFilterIds = extractDashboardFilterDisplayFormIdentifiers([drillDefinition]);
        const hasInvalidDashboardFilterParam = dashboardFilterIds.some((identifier) => {
            const displayForm = displayForms.get(identifier);
            if (!displayForm) {
                // target display form no longer exists, no reason to validate the parameters
                return true;
            }
            return (!sanitizedDashboardAttributeFilters.some((filter) => areObjRefsEqual(filterObjRef(filter), identifier)) &&
                !attributeFilterConfigs.some((config) => {
                    return config.displayAsLabel && areObjRefsEqual(config.displayAsLabel, identifier);
                }));
        });
        const insightFilterIds = extractInsightFilterDisplayFormIdentifiers([drillDefinition]);
        const hasInvalidInsightFilterParam = insightFilterIds.some((identifier) => {
            const displayForm = displayForms.get(identifier);
            if (!displayForm) {
                // target display form no longer exists, no reason to validate the parameters
                return true;
            }
            return !sanitizedWidgetAttributeFilters.some((filter) => areObjRefsEqual(filterObjRef(filter), identifier));
        });
        if (hasInvalidParam || hasInvalidDashboardFilterParam || hasInvalidInsightFilterParam) {
            acc.invalidDrills.push(drillDefinition);
        }
        return acc;
    }, { widget, invalidDrills: [] });
}
function sanitizeAttributeFilter(filter, displayFormMap) {
    const displayForm = displayFormMap.get(filterObjRef(filter));
    if (displayForm) {
        if (isNegativeAttributeFilter(filter)) {
            return {
                ...filter,
                negativeAttributeFilter: {
                    ...filter.negativeAttributeFilter,
                    displayForm: idRef(displayForm.id, "displayForm"),
                },
            };
        }
        else if (isArbitraryAttributeFilter(filter)) {
            return {
                ...filter,
                arbitraryAttributeFilter: {
                    ...filter.arbitraryAttributeFilter,
                    displayForm: idRef(displayForm.id, "displayForm"),
                },
            };
        }
        else if (isMatchAttributeFilter(filter)) {
            return {
                ...filter,
                matchAttributeFilter: {
                    ...filter.matchAttributeFilter,
                    displayForm: idRef(displayForm.id, "displayForm"),
                },
            };
        }
        else {
            return {
                ...filter,
                positiveAttributeFilter: {
                    ...filter.positiveAttributeFilter,
                    displayForm: idRef(displayForm.id, "displayForm"),
                },
            };
        }
    }
    return filter;
}
