// (C) 2021-2026 GoodData Corporation
import { groupBy, isEmpty } from "lodash-es";
import { defaultDateFilterConfig } from "./defaultConfig.js";
function getDuplicateIdentifiers(options) {
    const groups = groupBy(options, (filter) => filter.localIdentifier);
    const duplicates = Object.keys(groups).filter((localIdentifier) => groups[localIdentifier].length > 1);
    if (duplicates.length) {
        console.warn(`There were duplicate localIdentifiers in the date filter config: ${duplicates.join(",")}`);
    }
    return duplicates;
}
function isFilterVisible(filter) {
    return filter?.visible ?? false;
}
function containsVisibleFilter(filters) {
    return filters?.some(isFilterVisible) ?? false;
}
function isRelativeFormVisible(filter) {
    return isFilterVisible(filter) && !isEmpty(filter?.availableGranularities ?? []);
}
function isAnyFilterVisible(config) {
    return (isFilterVisible(config.allTime) ||
        isFilterVisible(config.absoluteForm) ||
        isRelativeFormVisible(config.relativeForm) ||
        containsVisibleFilter(config.absolutePresets) ||
        containsVisibleFilter(config.relativePresets));
}
function getAllOptionsFlattened(config) {
    const allPresets = [
        config.allTime,
        config.absoluteForm,
        config.relativeForm,
        ...(config.absolutePresets || []),
        ...(config.relativePresets || []),
    ];
    return allPresets.filter((item) => item !== undefined);
}
function isSelectedOptionValid(config) {
    // only presets and all time are allowed for now (RAIL-1598), so look only there
    const candidateOptions = [
        config.allTime,
        ...(config.absolutePresets || []),
        ...(config.relativePresets || []),
    ];
    const matchingOption = candidateOptions.find((option) => option?.localIdentifier === config.selectedOption);
    return matchingOption ? matchingOption.visible : false;
}
/**
 * Validates the provided date filter config. The config has a lot of options and not all of them can be
 * covered by the typing.
 *
 * @param config - config to validate
 * @param shouldCheckSelectedOption - indicate whether validation should check that a valid option is selected
 */
export function validateDateFilterConfig(config, shouldCheckSelectedOption = true) {
    if (!isAnyFilterVisible(config)) {
        return "NoVisibleOptions";
    }
    const allOptions = getAllOptionsFlattened(config);
    const duplicateIdentifiers = getDuplicateIdentifiers(allOptions);
    if (duplicateIdentifiers.length) {
        return "ConflictingIdentifiers";
    }
    return !shouldCheckSelectedOption || isSelectedOptionValid(config) ? "Valid" : "SelectedOptionInvalid";
}
export const FallbackToDefault = [
    "ConflictingIdentifiers",
    "NoVisibleOptions",
];
const conditionallyStripToDateFilters = (config, enableToDateFilters) => {
    if (enableToDateFilters) {
        return config;
    }
    return {
        ...config,
        relativePresets: config.relativePresets?.filter((preset) => !preset.boundedFilter) ?? [],
    };
};
const FISCAL_GRANULARITIES = [
    "GDC.time.fiscal_year",
    "GDC.time.fiscal_quarter",
    "GDC.time.fiscal_month",
];
export function configHasFiscalPresets(config) {
    return config?.relativePresets?.some((p) => FISCAL_GRANULARITIES.includes(p.granularity)) ?? false;
}
const getFiscalPresetsFromDefault = () => {
    return (defaultDateFilterConfig.relativePresets?.filter((preset) => FISCAL_GRANULARITIES.includes(preset.granularity)) ?? []);
};
const getFiscalGranularitiesFromDefault = () => {
    return (defaultDateFilterConfig.relativeForm?.availableGranularities.filter((g) => FISCAL_GRANULARITIES.includes(g)) ?? []);
};
const conditionallyHandleFiscalFilters = (config, enableFiscalCalendars) => {
    if (!enableFiscalCalendars) {
        return {
            ...config,
            relativePresets: config.relativePresets?.filter((preset) => !FISCAL_GRANULARITIES.includes(preset.granularity)) ?? [],
            relativeForm: config.relativeForm
                ? {
                    ...config.relativeForm,
                    availableGranularities: config.relativeForm.availableGranularities.filter((g) => !FISCAL_GRANULARITIES.includes(g)),
                }
                : undefined,
        };
    }
    const existingFiscalPresets = config.relativePresets?.filter((preset) => FISCAL_GRANULARITIES.includes(preset.granularity)) ?? [];
    const existingFiscalGranularities = config.relativeForm?.availableGranularities.filter((g) => FISCAL_GRANULARITIES.includes(g)) ?? [];
    if (existingFiscalPresets.length > 0 && existingFiscalGranularities.length > 0) {
        return config;
    }
    const fiscalPresetsToAdd = existingFiscalPresets.length === 0 ? getFiscalPresetsFromDefault() : [];
    const fiscalGranularitiesToAdd = existingFiscalGranularities.length === 0 ? getFiscalGranularitiesFromDefault() : [];
    return {
        ...config,
        relativePresets: [...(config.relativePresets ?? []), ...fiscalPresetsToAdd],
        relativeForm: config.relativeForm
            ? {
                ...config.relativeForm,
                availableGranularities: [
                    ...config.relativeForm.availableGranularities,
                    ...fiscalGranularitiesToAdd,
                ],
            }
            : undefined,
    };
};
const conditionallyHandleEmptyValues = (config, enableEmptyDateValuesFilter) => {
    if (!enableEmptyDateValuesFilter) {
        return config;
    }
    if (config.emptyValues || !defaultDateFilterConfig.emptyValues) {
        return config;
    }
    return {
        ...config,
        emptyValues: defaultDateFilterConfig.emptyValues,
    };
};
/**
 * Given the date filter config loaded from backend and the settings, this function will perform validation
 * of the config and if needed also cleanup of invalid/disabled presets.
 */
export function getValidDateFilterConfig(config, settings) {
    const configValidation = validateDateFilterConfig(config);
    let validConfig = FallbackToDefault.includes(configValidation) ? defaultDateFilterConfig : config;
    validConfig = conditionallyStripToDateFilters(validConfig, settings.enableToDateFilters ?? true);
    validConfig = conditionallyHandleFiscalFilters(validConfig, settings.enableFiscalCalendars ?? true);
    validConfig = conditionallyHandleEmptyValues(validConfig, settings.enableKDEmptyDateValuesFilter ?? true);
    return [validConfig, configValidation];
}
