// (C) 2020-2026 GoodData Corporation
import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, isDashboardDateFilterWithDimension, isLocalIdRef, measureAlias, measureFilters, measureLocalId, measureTitle, serializeObjRef, } from "@gooddata/sdk-model";
import { buildMeasureTitles } from "@gooddata/sdk-ui/internal";
import { sourceInsightFilterObjRefValue } from "../../../../../_staging/drills/drillingUtils.js";
import { canApplyFilterTypeToTarget } from "../../../../../model/commandHandlers/dashboard/common/attributeFilterSelectionTypeCompatibility.js";
import { findDashboardAttributeFilterByAttributeDisplayForms, findDashboardAttributeFilterByDisplayForm, findDashboardAttributeFilterByIncomingDisplayAsLabel, findDashboardAttributeFilterByTargetDisplayAsLabel, } from "../../../../../model/utils/filterContextUtils.js";
import { messages } from "./messages.js";
/**
 * Strip filter description suffix baked in by AD
 */
function stripMeasureFilterSuffix(measure, title) {
    const filters = measureFilters(measure);
    if (!filters?.length) {
        return title;
    }
    return title.replace(/ \([^)]+\)$/, "");
}
export function getMeasureTitleFromSourceInsightMeasures(sourceInsightMeasures, measureRef, allCatalogMeasures, intl) {
    if (!measureRef) {
        return undefined;
    }
    if (isLocalIdRef(measureRef)) {
        const sourceMeasure = sourceInsightMeasures.find((measure) => measureLocalId(measure) === measureRef.localIdentifier);
        if (!sourceMeasure) {
            return undefined;
        }
        const alias = measureAlias(sourceMeasure);
        if (alias) {
            return alias;
        }
        const title = measureTitle(sourceMeasure);
        if (title) {
            return stripMeasureFilterSuffix(sourceMeasure, title);
        }
        // For arithmetic and derived measures that don't have explicit titles,
        // build the title using buildMeasureTitles from sdk-ui.
        const locale = intl.locale;
        const messages = intl.messages;
        const allTitleProps = buildMeasureTitles(sourceInsightMeasures, locale, Number.MAX_SAFE_INTEGER, messages);
        const titleProp = allTitleProps.find((p) => p.localIdentifier === measureRef.localIdentifier);
        const builtTitle = titleProp?.alias ?? titleProp?.title;
        return builtTitle ? stripMeasureFilterSuffix(sourceMeasure, builtTitle) : builtTitle;
    }
    //fallback to catalog lookup in case of object ref
    return allCatalogMeasures.find((measure) => areObjRefsEqual(measure.measure.ref, measureRef))?.measure
        .title;
}
export function sourceFilterOptionId(sourceFilterObjRef) {
    return `${sourceFilterObjRef.type}:${serializeObjRef(sourceInsightFilterObjRefValue(sourceFilterObjRef))}`;
}
export function getDisabledOptionProps(disabled, message, selected) {
    return disabled
        ? {
            disabled: {
                message,
                selected,
            },
        }
        : {};
}
export function getDisabledOptionPropsForTransferResult(isDrillToDashboard, transferResult, intl) {
    if (!isDrillToDashboard || transferResult === "transferable") {
        return {};
    }
    const message = transferResult === "notCompatible"
        ? intl.formatMessage(messages.drillToDashboardFilterNotCompatibleTooltip)
        : intl.formatMessage(messages.drillToDashboardDashboardFilterTooltip);
    return getDisabledOptionProps(true, message, false);
}
export function getDisplayFormTitle({ displayFormRef, allCatalogDisplayFormsMap, }) {
    if (isLocalIdRef(displayFormRef)) {
        return "";
    }
    return allCatalogDisplayFormsMap.get(displayFormRef)?.title ?? "";
}
export function getDateDatasetTitle({ datasetRef, allCatalogDateDatasets, }) {
    const dateDataset = allCatalogDateDatasets.find((dataset) => areObjRefsEqual(dataset.dataSet.ref, datasetRef));
    return dateDataset?.dataSet.title ?? "";
}
export function getDashboardDateFilterCustomTitle({ datasetRef, allDateFilterConfigsOverrides, }) {
    const customTitle = allDateFilterConfigsOverrides.find((configOverride) => areObjRefsEqual(configOverride.dateDataSet, datasetRef))?.config.filterName;
    return customTitle || undefined;
}
export function hasMatchingTargetDashboardAttributeFilterDisplayForm(displayFormRef, targetDashboardAttributeFilters) {
    return !!findDashboardAttributeFilterByDisplayForm(targetDashboardAttributeFilters, displayFormRef);
}
export function hasMatchingTargetDashboardAttributeFilter(dashboardFilter, sourceDashboardAttributeFilterConfigs, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs, allCatalogDisplayFormsMap) {
    const displayFormRef = dashboardFilter.attributeFilter.displayForm;
    if (hasMatchingTargetDashboardAttributeFilterDisplayForm(displayFormRef, targetDashboardAttributeFilters)) {
        return true;
    }
    const sourceDisplayForm = allCatalogDisplayFormsMap.get(displayFormRef);
    if (sourceDisplayForm) {
        const attributeDisplayForms = Array.from(allCatalogDisplayFormsMap.values()).filter((displayForm) => areObjRefsEqual(displayForm.attribute, sourceDisplayForm.attribute));
        if (findDashboardAttributeFilterByAttributeDisplayForms(targetDashboardAttributeFilters, attributeDisplayForms)) {
            return true;
        }
    }
    if (findDashboardAttributeFilterByIncomingDisplayAsLabel(dashboardFilter, sourceDashboardAttributeFilterConfigs, targetDashboardAttributeFilters)) {
        return true;
    }
    return !!findDashboardAttributeFilterByTargetDisplayAsLabel(displayFormRef, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs);
}
export function hasMatchingTargetDashboardDateFilter(datasetRef, targetDashboardFilters) {
    return targetDashboardFilters.some((targetDashboardFilter) => isDashboardDateFilterWithDimension(targetDashboardFilter) &&
        areObjRefsEqual(datasetRef, targetDashboardFilter.dateFilter.dataSet));
}
export function isDateIntersectionAttribute(displayFormRef, allCatalogDateAttributeDisplayForms) {
    return allCatalogDateAttributeDisplayForms.some((displayForm) => areObjRefsEqual(displayForm.ref, displayFormRef));
}
function getConfigSelectionType(targetFilterLocalId, targetDashboardAttributeFilterConfigs) {
    return targetDashboardAttributeFilterConfigs.find((c) => c.localIdentifier === targetFilterLocalId)
        ?.selectionType;
}
/**
 * Finds a matching text filter on the target dashboard by displayForm.
 * Checks the source filter's displayForm and optionally its displayAsLabel from config.
 */
function findMatchingTargetTextFilter(displayFormRef, sourceDashboardAttributeFilterConfigs, sourceFilterLocalId, targetDashboardTextAttributeFilters) {
    // Direct displayForm match
    const directMatch = targetDashboardTextAttributeFilters.find((textFilter) => areObjRefsEqual(dashboardAttributeFilterItemDisplayForm(textFilter), displayFormRef));
    if (directMatch) {
        return directMatch;
    }
    // Check source's displayAsLabel from config
    if (sourceFilterLocalId) {
        const sourceConfig = sourceDashboardAttributeFilterConfigs.find((c) => c.localIdentifier === sourceFilterLocalId);
        if (sourceConfig?.displayAsLabel) {
            return targetDashboardTextAttributeFilters.find((textFilter) => areObjRefsEqual(dashboardAttributeFilterItemDisplayForm(textFilter), sourceConfig.displayAsLabel));
        }
    }
    return undefined;
}
/**
 * Finds a matching list filter on the target dashboard for a text source filter.
 * Text filter has only displayForm. List filter has primary displayForm + displayAsLabel in config.
 * Match if text filter's displayForm equals either of those.
 */
function findMatchingTargetListFilterForTextSource(textFilterDisplayFormRef, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs) {
    // Direct displayForm match
    const directMatch = findDashboardAttributeFilterByDisplayForm(targetDashboardAttributeFilters, textFilterDisplayFormRef);
    if (directMatch) {
        return directMatch;
    }
    // Check target's displayAsLabel — find a config whose displayAsLabel matches the text filter's displayForm
    return findDashboardAttributeFilterByTargetDisplayAsLabel(textFilterDisplayFormRef, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs);
}
/**
 * Checks if a list-type dashboard attribute filter can be transferred to the target dashboard,
 * considering both list and text filters on the target, and selection type config.
 */
export function canTransferDashboardAttributeFilter(sourceFilter, sourceDashboardAttributeFilterConfigs, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs, targetDashboardTextAttributeFilters, allCatalogDisplayFormsMap) {
    // 1. Same-type match against list filters — always OK
    if (hasMatchingTargetDashboardAttributeFilter(sourceFilter, sourceDashboardAttributeFilterConfigs, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs, allCatalogDisplayFormsMap)) {
        return "transferable";
    }
    // 2. Cross-type match against text filters on target
    const matchingTextFilter = findMatchingTargetTextFilter(sourceFilter.attributeFilter.displayForm, sourceDashboardAttributeFilterConfigs, sourceFilter.attributeFilter.localIdentifier, targetDashboardTextAttributeFilters);
    if (!matchingTextFilter) {
        return "notFound";
    }
    // 3. Check if the target text filter's selection type allows list type
    const textFilterLocalId = dashboardAttributeFilterItemLocalIdentifier(matchingTextFilter);
    if (!textFilterLocalId) {
        return "notFound";
    }
    const configSelectionType = getConfigSelectionType(textFilterLocalId, targetDashboardAttributeFilterConfigs);
    return canApplyFilterTypeToTarget("list", configSelectionType, matchingTextFilter)
        ? "transferable"
        : "notCompatible";
}
/**
 * Checks if a text-type dashboard attribute filter can be transferred to the target dashboard,
 * considering both text and list filters on the target, and selection type config.
 */
export function canTransferTextAttributeFilter(sourceFilter, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs, targetDashboardTextAttributeFilters) {
    const sourceDisplayFormRef = dashboardAttributeFilterItemDisplayForm(sourceFilter);
    // 1. Same-type match against text filters — always OK
    const matchingTextFilter = targetDashboardTextAttributeFilters.find((textFilter) => areObjRefsEqual(dashboardAttributeFilterItemDisplayForm(textFilter), sourceDisplayFormRef));
    if (matchingTextFilter) {
        return "transferable";
    }
    // 2. Cross-type match against list filters on target
    // Text filter has only displayForm; list filter has primary displayForm + displayAsLabel in config
    const matchingListFilter = findMatchingTargetListFilterForTextSource(sourceDisplayFormRef, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs);
    if (!matchingListFilter) {
        return "notFound";
    }
    // 3. Check if the target list filter's selection type allows text type
    const listFilterLocalId = matchingListFilter.attributeFilter.localIdentifier;
    if (!listFilterLocalId) {
        return "notFound";
    }
    const configSelectionType = getConfigSelectionType(listFilterLocalId, targetDashboardAttributeFilterConfigs);
    return canApplyFilterTypeToTarget("text", configSelectionType, matchingListFilter)
        ? "transferable"
        : "notCompatible";
}
/**
 * Checks if a source insight/measure attribute filter (by displayForm) can be transferred,
 * considering both list and text filters on the target, and selection type config.
 * Used for source insight filters and source measure filters where we only have a displayForm.
 *
 * @param displayFormRef - the displayForm of the source filter
 * @param isSourceTextFilter - whether the source filter is a text type (arbitrary/match)
 * @param targetDashboardAttributeFilters - list filters on the target dashboard
 * @param targetDashboardAttributeFilterConfigs - attribute filter configs on the target dashboard
 * @param targetDashboardTextAttributeFilters - text filters on the target dashboard
 */
export function canTransferAttributeFilterByDisplayForm(displayFormRef, isSourceTextFilter, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs, targetDashboardTextAttributeFilters) {
    if (isSourceTextFilter) {
        // Text source: check text targets first, then list targets with selection type
        const matchingTextFilter = targetDashboardTextAttributeFilters.find((textFilter) => areObjRefsEqual(dashboardAttributeFilterItemDisplayForm(textFilter), displayFormRef));
        if (matchingTextFilter) {
            return "transferable";
        }
        const matchingListFilter = findMatchingTargetListFilterForTextSource(displayFormRef, targetDashboardAttributeFilters, targetDashboardAttributeFilterConfigs);
        if (!matchingListFilter) {
            return "notFound";
        }
        const listFilterLocalId = matchingListFilter.attributeFilter.localIdentifier;
        if (!listFilterLocalId) {
            return "notFound";
        }
        const configSelectionType = getConfigSelectionType(listFilterLocalId, targetDashboardAttributeFilterConfigs);
        return canApplyFilterTypeToTarget("text", configSelectionType, matchingListFilter)
            ? "transferable"
            : "notCompatible";
    }
    // List source: check list targets first, then text targets with selection type
    if (hasMatchingTargetDashboardAttributeFilterDisplayForm(displayFormRef, targetDashboardAttributeFilters)) {
        return "transferable";
    }
    const matchingTextFilter = targetDashboardTextAttributeFilters.find((textFilter) => areObjRefsEqual(dashboardAttributeFilterItemDisplayForm(textFilter), displayFormRef));
    if (!matchingTextFilter) {
        return "notFound";
    }
    const textFilterLocalId = dashboardAttributeFilterItemLocalIdentifier(matchingTextFilter);
    if (!textFilterLocalId) {
        return "notFound";
    }
    const configSelectionType = getConfigSelectionType(textFilterLocalId, targetDashboardAttributeFilterConfigs);
    return canApplyFilterTypeToTarget("list", configSelectionType, matchingTextFilter)
        ? "transferable"
        : "notCompatible";
}
//# sourceMappingURL=drillFiltersConfigUtils.js.map